Просмотр исходного кода

Change text animator to variable length character type

ipatix 7 лет назад
Родитель
Сommit
7a3ee40ada
1 измененных файлов: 196 добавлений и 45 удалений
  1. 196
    45
      src/overworld/tileset_animation/text_animator.c

+ 196
- 45
src/overworld/tileset_animation/text_animator.c Просмотреть файл

@@ -1,6 +1,8 @@
1 1
 #include <pokeagb/pokeagb.h>
2
+#include <agb_debug.h>
2 3
 #include <tileset_animation/font.h>
3 4
 #include <config.h>
5
+#include <assert.h>
4 6
 
5 7
 #define CANVAS_X_START (22)
6 8
 #define CANVAS_Y_START (35)
@@ -10,64 +12,213 @@
10 12
 #define CANVAS_FIRST ((u8 *)(574 * 0x20 + 0x06000000))
11 13
 #define CANVAS_SECOND ((u8 *)(592 * 0x20 + 0x06000000))
12 14
 
13
-static const char *map_texts[] = {"--------", "< Carun City", "Route 2 >", "< Route 3", "< Urbania City", "Route 5 >", "< Route 6", NULL};
14
-
15
-s16 char_to_tile_index(char chr) {
16
-    if (chr >= 'A' && chr <= 'P')
17
-        return chr - 'A';
18
-    if (chr >= 'Q' && chr <= 'Z')
19
-        return (16 * 2) + (chr - 'Q');
20
-    if (chr >= '0' && chr <= '9')
21
-        return (16 * 8) + (chr - '0');
22
-    if (chr >= 'a' && chr <= 'p')
23
-        return (16 * 4) + (chr - 'a');
24
-    if (chr >= 'q' && chr <= 'z')
25
-        return (16 * 6) + (chr - 'q');
26
-    if (chr == '<')
27
-        return char_to_tile_index('z') + 1;
28
-    if (chr == '>')
29
-        return char_to_tile_index('z') + 2;
30
-    if (chr == ' ')
31
-        return char_to_tile_index('9') + 1;
32
-    return -1;
15
+static const char *map_texts[] = {"--------", "← Carun City", "Route 2 >", "< Route 3", "< Urbania City", "Route 5 >", "< Route 6", NULL};
16
+
17
+/*
18
+ * Tile IDs:
19
+ * 0x00: ABCDEFGH
20
+ * 0x08: IJKLMNOP
21
+ * 0x10: QRSTUVWX
22
+ * 0x18: YZÄÖÜäöü
23
+ * 0x20: abcdefgh
24
+ * 0x28: ijklmnop
25
+ * 0x30: qrstuvwx
26
+ * 0x38: yz←→!?↑↓
27
+ * 0x40: 01234567
28
+ * 0x48: 89,.;:⚠ 
29
+ */
30
+
31
+static const u8 font_length_table[] = {
32
+    6, 6, 6, 6, 6, 6, 6, 6,
33
+    4, 5, 6, 5, 6, 6, 6, 6,
34
+    6, 6, 6, 6, 6, 6, 6, 6,
35
+    6, 6, 6, 6, 6, 5, 5, 5,
36
+    5, 5, 5, 5, 5, 5, 5, 5,
37
+    2, 3, 5, 2, 8, 5, 5, 5,
38
+    5, 4, 4, 4, 5, 6, 8, 5,
39
+    5, 5, 8, 8, 2, 4, 6, 6,
40
+    6, 4, 6, 6, 6, 6, 6, 6,
41
+    6, 6, 3, 2, 3, 2, 8, 4,
42
+};
43
+
44
+static const u8 tile_id_table[] = {
45
+    0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, // 0x0
46
+    0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, // 0x8
47
+    0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, // 0x10
48
+    0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, // 0x18
49
+    0x4F, 0x3C, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, // 0x20
50
+    0x4E, 0x4E, 0x4E, 0x4E, 0x4A, 0x4E, 0x4B, 0x4E, // 0x28
51
+    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, // 0x30
52
+    0x48, 0x49, 0x4D, 0x4C, 0x4E, 0x4E, 0x4E, 0x3D, // 0x38
53
+
54
+    0x4E, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // 0x40
55
+    0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, // 0x48
56
+    0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, // 0x50
57
+    0x17, 0x18, 0x19, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, // 0x58
58
+    0x4E, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, // 0x60
59
+    0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, // 0x68
60
+    0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, // 0x70
61
+    0x37, 0x38, 0x39, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, // 0x78
62
+};
63
+
64
+static u8 iterate_tilenum(const char **iterator) {
65
+    u8 c = *((*iterator)++);
66
+    if (c <= 0x7F) {
67
+        return tile_id_table[c];
68
+    } else {
69
+        if (c == 0xE2) {
70
+            // arrow symbols in utf-8
71
+            c = *((*iterator)++);
72
+            if (c == 0x86) {
73
+                c = *((*iterator)++);
74
+                if (c == 0x90) {
75
+                    return 0x3A; // ←
76
+                } else if (c == 0x91) {
77
+                    return 0x3E; // ↑
78
+                } else if (c == 0x92) {
79
+                    return 0x3B; // →
80
+                } else if (c == 0x93) {
81
+                    return 0x3F; // ↓
82
+                } else {
83
+                    return 0x4E;
84
+                }
85
+            } else {
86
+                return 0x4E;
87
+            }
88
+        } else if (c == 0xC3) {
89
+            // umlaute in utf-8
90
+            c = *((*iterator)++);
91
+            if (c == 0x84) {
92
+                return 0x1A; // Ä
93
+            } else if (c == 0x96) {
94
+                return 0x1B; // Ö
95
+            } else if (c == 0x9C) {
96
+                return 0x1C; // Ü
97
+            } else if (c == 0xA4) {
98
+                return 0x1D; // ä
99
+            } else if (c == 0xB6) {
100
+                return 0x1E; // ö
101
+            } else if (c == 0xBC) {
102
+                return 0x1F;
103
+            } else {
104
+                return 0x4E;
105
+            }
106
+        } else {
107
+            return 0x4E; // invalid symbol
108
+        }
109
+    }
33 110
 }
34 111
 
112
+static const size_t tile8x8size = 0x20;
113
+
35 114
 void draw_text_on_canvas(const char *txt) {
115
+    u32 *video_mem_a = (u32 *)CANVAS_FIRST;
116
+    u32 *video_mem_b = (u32 *)CANVAS_SECOND;
117
+
118
+    u32 rendered_tile_a[8];
119
+    u32 rendered_tile_b[8];
120
+
121
+    u32 cur_tile_index = 0;
36 122
 
37
-    u16 current_tile = 0;
38 123
     while (*txt) {
39
-        s16 tile = char_to_tile_index(*txt);
40
-        if (tile != -1) {
41
-            void *first = CANVAS_FIRST + (current_tile * 0x20);
42
-            void *second = CANVAS_SECOND + (current_tile * 0x20);
43
-            memcpy(first, fontTiles + (tile * 0x20), 0x20);
44
-            memcpy(second, fontTiles + (16 * 0x20) + (tile * 0x20), 0x20);
124
+        const u8 sym = iterate_tilenum(&txt);
125
+        const u32 tile_index = (((sym >> 4) << 5) | (sym & 0xF)) * tile8x8size;
126
+        const u8 sym_width = font_length_table[sym];
127
+        u32 *cur_source_tile_a = (u32 *)(fontTiles + tile_index);
128
+        u32 *cur_source_tile_b = (u32 *)((u8 *)cur_source_tile_a + tile8x8size * 16);
129
+        if (cur_tile_index == 0) {
130
+            for (int i = 0; i < 8; i++) {
131
+                u32 pxl_row_a = *cur_source_tile_a++;
132
+                pxl_row_a <<= (4 * (8 - sym_width));
133
+                pxl_row_a >>= (4 * (8 - sym_width));
134
+                rendered_tile_a[i] = pxl_row_a;
135
+
136
+                u32 pxl_row_b = *cur_source_tile_b++;
137
+                pxl_row_b <<= (4 * (8 - sym_width));
138
+                pxl_row_b >>= (4 * (8 - sym_width));
139
+                rendered_tile_b[i] = pxl_row_b;
140
+            }
141
+        } else if (cur_tile_index + sym_width >= 8) {
142
+            for (int i = 0; i < 8; i++) {
143
+                u32 pxl_row_a = *cur_source_tile_a++;
144
+                pxl_row_a <<= (4 * cur_tile_index);
145
+                rendered_tile_a[i] |= pxl_row_a;        // <-- differs to line above
146
+
147
+                u32 pxl_row_b = *cur_source_tile_b++;
148
+                pxl_row_b <<= (4 * cur_tile_index);
149
+                rendered_tile_b[i] |= pxl_row_b;        // <-- differs to line above
150
+            }
151
+        } else {
152
+            for (int i = 0; i < 8; i++) {
153
+                u32 pxl_row_a = *cur_source_tile_a++;
154
+                pxl_row_a <<= (4 * (8 - sym_width));
155
+                pxl_row_a >>= (4 * (8 - cur_tile_index - sym_width));
156
+                rendered_tile_a[i] |= pxl_row_a;        // <-- differs to line above
157
+
158
+                u32 pxl_row_b = *cur_source_tile_b++;
159
+                pxl_row_b <<= (4 * (8 - sym_width));
160
+                pxl_row_b >>= (4 * (8 - cur_tile_index - sym_width));
161
+                rendered_tile_b[i] |= pxl_row_b;        // <-- differs to line above
162
+            }
163
+        }
164
+
165
+        cur_tile_index += sym_width;
166
+
167
+        // one tile fully rendered, emit to video mem
168
+        if (cur_tile_index >= 8) {
169
+            for (int i = 0; i < 8; i++) {
170
+                *video_mem_a++ = rendered_tile_a[i];
171
+                *video_mem_b++ = rendered_tile_b[i];
172
+            }
173
+            cur_tile_index -= 8;
174
+            if (cur_tile_index > 0) {
175
+                cur_source_tile_a = (u32 *)(fontTiles + tile_index);
176
+                cur_source_tile_b = (u32 *)((u8 *)cur_source_tile_a + tile8x8size * 16);
177
+                for (int i = 0; i < 8; i++) {
178
+                    u32 pxl_row_a = *cur_source_tile_a++;
179
+                    pxl_row_a <<= (4 * (8 - sym_width));
180
+                    pxl_row_a >>= (4 * (8 - cur_tile_index));
181
+                    rendered_tile_a[i] = pxl_row_a;
182
+
183
+                    u32 pxl_row_b = *cur_source_tile_b++;
184
+                    pxl_row_b <<= (4 * (8 - sym_width));
185
+                    pxl_row_b >>= (4 * (8 - cur_tile_index));
186
+                    rendered_tile_b[i] = pxl_row_b;
187
+                }
188
+            }
45 189
         }
46
-        txt++;
47
-        current_tile++;
48 190
     }
49
-}
50 191
 
51
-u8 get_pixel(u8 x, u8 y, u16 *start) {
52
-    u16 block = start[16 * (x / 4) + 2 * y + ((x % 4) / 2)];
53
-    if (x % 2 == 0)
54
-        return block & 0xFF;
192
+    // check if there is rendered tiles which aren't in video mem yet
193
+    //assert(cur_tile_index < 8);
194
+    if (cur_tile_index > 0) {
195
+        const u8 sym = 0x4F;
196
+        const u32 tile_index = (((sym >> 4) << 5) | (sym & 0xF)) * tile8x8size;
197
+        u32 *cur_source_tile_a = (u32 *)(fontTiles + tile_index);
198
+        u32 *cur_source_tile_b = (u32 *)((u8 *)cur_source_tile_a + tile8x8size * 16);
55 199
 
56
-    return (block >> 8);
57
-}
200
+        for (int i = 0; i < 8; i++) {
201
+            u32 pxl_row_a = *cur_source_tile_a++;
202
+            pxl_row_a <<= (4 * cur_tile_index);
203
+            rendered_tile_a[i] |= pxl_row_a;        // <-- differs to line above
58 204
 
59
-void set_pixel(u8 x, u8 y, u16 *start, u16 pixel) {
60
-    pixel &= 0xFF;
61
-    u16 *addr = &start[16 * (x / 4) + 2 * y + ((x % 4) / 2)];
62
-    if (x % 2 == 0)
63
-        *addr = (*addr & 0xFF00) | (pixel);
64
-    else
65
-        *addr = (*((u8 *)addr)) | (pixel << 8);
205
+            u32 pxl_row_b = *cur_source_tile_b++;
206
+            pxl_row_b <<= (4 * cur_tile_index);
207
+            rendered_tile_b[i] |= pxl_row_b;        // <-- differs to line above
208
+        }
209
+
210
+        for (int i = 0; i < 8; i++) {
211
+            *video_mem_a++ = rendered_tile_a[i];
212
+            *video_mem_b++ = rendered_tile_b[i];
213
+        }
214
+    }
66 215
 }
67 216
 
68
-#define ANIMATION_FRAME_SPEED 2
217
+#define ANIMATION_FRAME_SPEED ((unsigned int)2)
69 218
 
70
-/* TODO: Compile RELEASE Versions of the game with higher optimization flags */
219
+_Static_assert(ANIMATION_FRAME_SPEED && !(ANIMATION_FRAME_SPEED & (ANIMATION_FRAME_SPEED - 1)),
220
+        "Text Banner animation speed is not power of 2");
221
+// check if the speed is a power of two so no division get's created
71 222
 
72 223
 #define TEXT_ANIM_TILE_ROW(c, x, y) (((u32 *)c)[x * 8 + y])
73 224