1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - WBT - demos - wbt-1
3 File: text.c
4
5 Copyright 2006-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-18#$
14 $Rev: 8573 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #ifdef SDK_TWL
19 #include <twl.h>
20 #else
21 #include <nitro.h>
22 #endif
23
24 #include "text.h"
25
26 #define TAB_SIZE 8
27 /*****************************************************/
28
29 static LINE_BUF *lb_free_ptr;
30 static int x_size = X_LINE_MAX;
31 static int y_size = Y_LINE_MAX;
32
link_line_buf(LINE_BUF * m,LINE_BUF * s)33 static void link_line_buf(LINE_BUF * m, LINE_BUF * s)
34 {
35 if (m->next != NULL)
36 {
37 s->next = m->next;
38 (s->next)->prev = s;
39 }
40 else
41 s->next = NULL;
42
43 m->next = s;
44 s->prev = m;
45 }
46
unlink_line_buf(LINE_BUF * s)47 static void unlink_line_buf(LINE_BUF * s)
48 {
49 if ((s->prev != NULL) && (s->next != NULL))
50 {
51 (s->prev)->next = s->next;
52 (s->next)->prev = s->prev;
53 s->next = NULL;
54 s->prev = NULL;
55 }
56 else if (s->next != NULL)
57 {
58 s->prev = NULL;
59 (s->next)->prev = NULL;
60 s->next = NULL;
61 }
62 else if (s->prev != NULL)
63 {
64 s->next = NULL;
65 (s->prev)->next = NULL;
66 s->prev = NULL;
67 }
68 }
69
alloc_line_buf(void)70 static LINE_BUF *alloc_line_buf(void)
71 {
72 LINE_BUF *tmp;
73 tmp = lb_free_ptr;
74 lb_free_ptr = lb_free_ptr->next;
75 unlink_line_buf(tmp);
76 tmp->last_count = 0;
77 tmp->cur_count = 0;
78 #if 0
79 for (i = 0; i < LINE_BUF_X_SIZE; i++)
80 tmp->buf[i] = 0x20;
81 #endif
82 return (tmp);
83 }
84
free_line_buf(LINE_BUF * lb)85 static void free_line_buf(LINE_BUF * lb)
86 {
87 lb->next = lb_free_ptr;
88 lb->prev = NULL;
89 (lb->next)->prev = lb;
90 lb_free_ptr = lb;
91 }
92
init_lb_heap(void * heap_start,void * heap_end)93 static int init_lb_heap(void *heap_start, void *heap_end)
94 {
95 int i;
96 LINE_BUF *lb_heap = (LINE_BUF *) heap_start;
97 lb_free_ptr = (LINE_BUF *) heap_start;
98 lb_heap[0].prev = NULL;
99
100 i = 0;
101 while ((u32)&(lb_heap[i + 1]) < (u32)heap_end)
102 {
103 link_line_buf(&(lb_heap[i]), &(lb_heap[i + 1]));
104 i++;
105 }
106 lb_heap[i].next = NULL;
107 return i; /* Num of line buffer */
108 }
109
init_text_buf(TEXT_BUF * tb)110 static void init_text_buf(TEXT_BUF * tb)
111 {
112 tb->num_y = &y_size;
113 tb->num_x = &x_size;
114 tb->start = tb->cur = alloc_line_buf();
115 }
116
117
init_text(TEXT_CTRL * tc,u16 * screen,u16 palette)118 void init_text(TEXT_CTRL * tc, u16 *screen, u16 palette)
119 {
120 tc->screen = screen;
121 tc->x_line = 0;
122 tc->y_line = 0;
123 tc->palette = palette;
124 init_text_buf(&(tc->text_buf));
125 }
126
127
128
m_set_palette(TEXT_CTRL * tc,u16 num)129 void m_set_palette(TEXT_CTRL * tc, u16 num)
130 {
131 tc->palette = (u16)(0x0f & num);
132 }
133
m_get_palette(TEXT_CTRL * tc)134 u16 m_get_palette(TEXT_CTRL * tc)
135 {
136 return tc->palette;
137 }
138
clear_line(TEXT_CTRL * tc)139 static void clear_line(TEXT_CTRL * tc)
140 {
141 int i;
142 i = tc->x_line;
143
144 for (; i < X_LINE_MAX; i++)
145 tc->screen[(tc->y_line * X_LINE_MAX) + i] = 0;
146
147 }
148
add_y_line(TEXT_CTRL * tc,u16 num)149 static void add_y_line(TEXT_CTRL * tc, u16 num)
150 {
151 tc->y_line += num;
152 if (tc->y_line > Y_LINE_MAX)
153 {
154 tc->y_line = 0;
155 }
156 }
157
add_x_line(TEXT_CTRL * tc,u16 num)158 static void add_x_line(TEXT_CTRL * tc, u16 num)
159 {
160 tc->x_line += num;
161
162 if (tc->x_line > X_LINE_MAX)
163 {
164 tc->x_line = 0;
165 tc->y_line++;
166 if (tc->y_line > Y_LINE_MAX)
167 {
168 tc->y_line = 0;
169 }
170 }
171 }
172
put_char_vram(TEXT_CTRL * tc,int c,u16 col)173 static void put_char_vram(TEXT_CTRL * tc, int c, u16 col)
174 {
175
176 switch (c)
177 {
178 case '\0':
179 break;
180 case '\n':
181 clear_line(tc);
182 tc->x_line = 0;
183 add_y_line(tc, 1);
184 break;
185 case '\r':
186 tc->x_line = 0;
187 break;
188 case '\t':
189 add_x_line(tc, TAB_SIZE);
190 break;
191 case '\f':
192 tc->x_line = 0;
193 tc->y_line = 0;
194 clear_line(tc);
195 break;
196 case '\b': /* Backspace */
197 case '\v': /* Vertical Tab */
198 break;
199 default:
200 if ((c < 0x20) || (0x7f < c))
201 c = 0x20; /* Whitespace */
202 tc->screen[(tc->y_line * X_LINE_MAX) + tc->x_line] = (u16)((col << 12) | (0x00ff & c));
203 add_x_line(tc, 1);
204 }
205 }
206
207 /**********************/
208
m_putchar(TEXT_CTRL * tc,int c)209 void m_putchar(TEXT_CTRL * tc, int c)
210 {
211 int i;
212 LINE_BUF *tmp;
213 TEXT_BUF *tb = &(tc->text_buf);
214
215 switch (c)
216 {
217 case '\0':
218 break;
219 case '\n':
220 if (tb->cur->next == NULL)
221 {
222 tmp = tb->cur; /* Recalculate the display start buffer */
223 for (i = 0; i < *(tb->num_y) - 1 && i < LINE_BUF_Y_SIZE; i++)
224 {
225 if (tmp->prev == NULL)
226 break;
227 tmp = tmp->prev;
228 }
229 tb->start = tmp;
230 while (tmp->prev != NULL)
231 { /* Deallocate unnecessary buffers */
232 tmp = tmp->prev;
233 unlink_line_buf(tmp);
234 free_line_buf(tmp);
235 }
236 tmp = alloc_line_buf(); /* Get one buffer */
237
238 link_line_buf(tb->cur, tmp); /* Link the obtained buffer to the next buffer from the current buffer
239 */
240 tb->cur = tmp; /* Update the current buffer */
241 tb->cur->cur_count = 0;
242 tb->cur->last_count = 0;
243 }
244 else
245 {
246 tb->cur = tb->cur->next;
247 tb->cur->cur_count = 0;
248 tb->cur->last_count = 0;
249 }
250 break;
251 case '\r':
252 tb->cur->cur_count = 0;
253 break;
254 case '\t':
255 tb->cur->cur_count += TAB_SIZE;
256 if (tb->cur->cur_count > LINE_BUF_X_SIZE)
257 tb->cur->cur_count = LINE_BUF_X_SIZE;
258 if (tb->cur->cur_count > tb->cur->last_count)
259 tb->cur->last_count = tb->cur->cur_count;
260 break;
261 case '\f':
262 tb->cur = tb->start;
263 tb->cur->cur_count = 0;
264 tb->cur->last_count = 0;
265 break;
266 case '\a': /* BELL */
267 break;
268 case '\b': /* Backspace */
269 if (tb->cur->cur_count > 0)
270 tb->cur->cur_count--;
271 break;
272 case '\v': /* Vertical Tab */
273 break;
274 default:
275 tb->cur->buf[tb->cur->cur_count] = c;
276 tb->cur->col[tb->cur->cur_count] = tc->palette;
277 tb->cur->cur_count++;
278 if (tb->cur->cur_count > LINE_BUF_X_SIZE)
279 {
280 tb->cur->cur_count = LINE_BUF_X_SIZE;
281 break;
282 }
283 if (tb->cur->cur_count > tb->cur->last_count)
284 tb->cur->last_count = tb->cur->cur_count;
285 break;
286 }
287 }
288
289
init_text_buf_sys(void * heap_start,void * heap_end)290 int init_text_buf_sys(void *heap_start, void *heap_end)
291 {
292 return init_lb_heap(heap_start, heap_end);
293 }
294
295
text_buf_to_vram(TEXT_CTRL * tc)296 void text_buf_to_vram(TEXT_CTRL * tc)
297 {
298 int x_line, line_no;
299 int c;
300 u16 col;
301 LINE_BUF *lb;
302 TEXT_BUF *tb = &(tc->text_buf);
303
304
305 lb = tb->start;
306
307 put_char_vram(tc, '\f', (u16)0);
308
309 for (line_no = 0; line_no < (*tb->num_y + 1); line_no++)
310 {
311 x_line = 0;
312 if (lb == NULL)
313 break;
314 while (x_line < lb->last_count)
315 {
316 if (x_line >= (*tb->num_x + 1))
317 {
318 break;
319 }
320 else
321 {
322 c = lb->buf[x_line];
323 col = lb->col[x_line];
324 put_char_vram(tc, c, col);
325 }
326 x_line++;
327 }
328
329 if (x_line <= *tb->num_x)
330 {
331 put_char_vram(tc, '\n', (u16)0);
332 }
333 lb = lb->next;
334 }
335
336 for (; line_no <= *tb->num_y; line_no++)
337 {
338 put_char_vram(tc, '\n', (u16)0);
339 }
340 }
341
342
mprintf(const char * text,...)343 void mprintf(const char *text, ...)
344 {
345 va_list vlist;
346 char temp[32];
347 s32 i = 0;
348
349 va_start(vlist, text);
350 (void)OS_VSNPrintf(temp, 32, text, vlist);
351 va_end(vlist);
352 for (i = 0; i < 33; i++)
353 {
354 m_putchar(tc[0], (int)temp[i]);
355 if (temp[i] == '\n')
356 {
357 break;
358 }
359 }
360 if (i > 32)
361 m_putchar(tc[0], '\n');
362
363 }
364
mfprintf(TEXT_CTRL * tc,const char * text,...)365 void mfprintf(TEXT_CTRL * tc, const char *text, ...)
366 {
367 va_list vlist;
368 char temp[32];
369 s32 i = 0;
370
371 va_start(vlist, text);
372 (void)OS_VSNPrintf(temp, 32, text, vlist);
373 va_end(vlist);
374 for (i = 0; i < 33; i++)
375 {
376 m_putchar(tc, (int)temp[i]);
377 if (temp[i] == '\n')
378 {
379 break;
380 }
381
382 }
383 if (i > 32)
384 m_putchar(tc, '\n');
385 }
386