1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - WXC - demos - unregister-1
3 File: text.c
4
5 Copyright 2005-2009 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:: 2007-11-15#$
14 $Rev: 2414 $
15 $Author: hatamoto_minoru $
16 *---------------------------------------------------------------------------*/
17
18
19 #include <nitro.h>
20 #include "font.h"
21 #include "text.h"
22
23 #define TAB_SIZE 8
24 /*****************************************************/
25
26 static LINE_BUF *lb_free_ptr;
27 static int x_size = X_LINE_MAX;
28 static int y_size = Y_LINE_MAX;
29
link_line_buf(LINE_BUF * m,LINE_BUF * s)30 static void link_line_buf(LINE_BUF * m, LINE_BUF * s)
31 {
32 if (m->next != NULL)
33 {
34 s->next = m->next;
35 (s->next)->prev = s;
36 }
37 else
38 s->next = NULL;
39
40 m->next = s;
41 s->prev = m;
42 }
43
unlink_line_buf(LINE_BUF * s)44 static void unlink_line_buf(LINE_BUF * s)
45 {
46 if ((s->prev != NULL) && (s->next != NULL))
47 {
48 (s->prev)->next = s->next;
49 (s->next)->prev = s->prev;
50 s->next = NULL;
51 s->prev = NULL;
52 }
53 else if (s->next != NULL)
54 {
55 s->prev = NULL;
56 (s->next)->prev = NULL;
57 s->next = NULL;
58 }
59 else if (s->prev != NULL)
60 {
61 s->next = NULL;
62 (s->prev)->next = NULL;
63 s->prev = NULL;
64 }
65 }
66
alloc_line_buf(void)67 static LINE_BUF *alloc_line_buf(void)
68 {
69 LINE_BUF *tmp;
70 tmp = lb_free_ptr;
71 lb_free_ptr = lb_free_ptr->next;
72 unlink_line_buf(tmp);
73 tmp->last_count = 0;
74 tmp->cur_count = 0;
75 #if 0
76 for (i = 0; i < LINE_BUF_X_SIZE; i++)
77 tmp->buf[i] = 0x20;
78 #endif
79 return (tmp);
80 }
81
free_line_buf(LINE_BUF * lb)82 static void free_line_buf(LINE_BUF * lb)
83 {
84 lb->next = lb_free_ptr;
85 lb->prev = NULL;
86 (lb->next)->prev = lb;
87 lb_free_ptr = lb;
88 }
89
init_lb_heap(void * heap_start,void * heap_end)90 static int init_lb_heap(void *heap_start, void *heap_end)
91 {
92 int i;
93 LINE_BUF *lb_heap = (LINE_BUF *) heap_start;
94 lb_free_ptr = (LINE_BUF *) heap_start;
95 lb_heap[0].prev = NULL;
96
97 i = 0;
98 while ((u32)&(lb_heap[i + 1]) < (u32)heap_end)
99 {
100 link_line_buf(&(lb_heap[i]), &(lb_heap[i + 1]));
101 i++;
102 }
103 lb_heap[i].next = NULL;
104 return i; /* Num of line buffer */
105 }
106
init_text_buf(TEXT_BUF * tb)107 static void init_text_buf(TEXT_BUF * tb)
108 {
109 tb->num_y = &y_size;
110 tb->num_x = &x_size;
111 tb->start = tb->cur = alloc_line_buf();
112 }
113
114
init_text(TEXT_CTRL * tc,u16 * screen,u16 palette)115 void init_text(TEXT_CTRL * tc, u16 *screen, u16 palette)
116 {
117 tc->screen = screen;
118 tc->x_line = 0;
119 tc->y_line = 0;
120 tc->palette = palette;
121 init_text_buf(&(tc->text_buf));
122 }
123
124
125
m_set_palette(TEXT_CTRL * tc,u16 num)126 void m_set_palette(TEXT_CTRL * tc, u16 num)
127 {
128 tc->palette = (u16)(0x0f & num);
129 }
130
m_get_palette(TEXT_CTRL * tc)131 u16 m_get_palette(TEXT_CTRL * tc)
132 {
133 return tc->palette;
134 }
135
clear_line(TEXT_CTRL * tc)136 static void clear_line(TEXT_CTRL * tc)
137 {
138 int i;
139 i = tc->x_line;
140
141 for (; i < X_LINE_MAX; i++)
142 tc->screen[(tc->y_line * X_LINE_MAX) + i] = 0x20;
143
144 }
145
add_y_line(TEXT_CTRL * tc,u16 num)146 static void add_y_line(TEXT_CTRL * tc, u16 num)
147 {
148 tc->y_line += num;
149 if (tc->y_line > Y_LINE_MAX - 1)
150 {
151 tc->y_line = 0;
152 }
153 }
154
add_x_line(TEXT_CTRL * tc,u16 num)155 static void add_x_line(TEXT_CTRL * tc, u16 num)
156 {
157 tc->x_line += num;
158 if (tc->x_line > X_LINE_MAX - 1)
159 {
160 tc->x_line = 0;
161 add_y_line(tc, 1);
162 }
163 }
164
165
166 /**********************/
167
m_putchar(TEXT_CTRL * tc,int c)168 void m_putchar(TEXT_CTRL * tc, int c)
169 {
170 int i;
171 LINE_BUF *tmp;
172 TEXT_BUF *tb = &(tc->text_buf);
173
174 switch (c)
175 {
176 case '\0':
177 break;
178 case '\n':
179 if (tb->cur->next == NULL)
180 {
181 tmp = tb->cur; /* Recalculate the display start buffer */
182 for (i = 0; i < *(tb->num_y) - 1 && i < LINE_BUF_Y_SIZE; i++)
183 {
184 if (tmp->prev == NULL)
185 break;
186 tmp = tmp->prev;
187 }
188 tb->start = tmp;
189 while (tmp->prev != NULL)
190 { /* Deallocate unnecessary buffers */
191 tmp = tmp->prev;
192 unlink_line_buf(tmp);
193 free_line_buf(tmp);
194 }
195 tmp = alloc_line_buf(); /* Get one buffer */
196
197 link_line_buf(tb->cur, tmp); /* Link the obtained buffer as the next buffer to the current one
198 */
199 tb->cur = tmp; /* Update the current buffer */
200 tb->cur->cur_count = 0;
201 tb->cur->last_count = 0;
202 }
203 else
204 {
205 tb->cur = tb->cur->next;
206 tb->cur->cur_count = 0;
207 tb->cur->last_count = 0;
208 }
209 break;
210 case '\r':
211 tb->cur->cur_count = 0;
212 break;
213 case '\t':
214 tb->cur->cur_count += TAB_SIZE;
215 if (tb->cur->cur_count > LINE_BUF_X_SIZE)
216 tb->cur->cur_count = LINE_BUF_X_SIZE;
217 if (tb->cur->cur_count > tb->cur->last_count)
218 tb->cur->last_count = tb->cur->cur_count;
219 break;
220 case '\f':
221 tb->cur = tb->start;
222 tb->cur->cur_count = 0;
223 tb->cur->last_count = 0;
224 break;
225 case '\a': /* BELL */
226 break;
227 case '\b': /* Backspace */
228 if (tb->cur->cur_count > 0)
229 tb->cur->cur_count--;
230 break;
231 case '\v': /* Vertical Tab */
232 break;
233 default:
234 tb->cur->buf[tb->cur->cur_count] = c;
235 tb->cur->col[tb->cur->cur_count] = tc->palette;
236 tb->cur->cur_count++;
237 if (tb->cur->cur_count > LINE_BUF_X_SIZE)
238 {
239 tb->cur->cur_count = LINE_BUF_X_SIZE;
240 break;
241 }
242 if (tb->cur->cur_count > tb->cur->last_count)
243 {
244 tb->cur->last_count = tb->cur->cur_count;
245 }
246 break;
247 }
248 }
249
250
init_text_buf_sys(void * heap_start,void * heap_end)251 int init_text_buf_sys(void *heap_start, void *heap_end)
252 {
253 return init_lb_heap(heap_start, heap_end);
254 }
255
256
put_char_vram(TEXT_CTRL * tc,int c,u16 col)257 static void put_char_vram(TEXT_CTRL * tc, int c, u16 col)
258 {
259
260 switch (c)
261 {
262 case '\0':
263 break;
264 case '\n':
265 clear_line(tc);
266 tc->x_line = 0;
267 add_y_line(tc, 1);
268 break;
269 case '\r':
270 tc->x_line = 0;
271 break;
272 case '\t':
273 add_x_line(tc, TAB_SIZE);
274 break;
275 case '\f':
276 tc->x_line = 0;
277 tc->y_line = 0;
278 clear_line(tc);
279 break;
280 case '\b': /* Backspace */
281 case '\v': /* Vertical Tab */
282 break;
283 default:
284 if ((c < 0x20) || (0x7f < c))
285 c = 0x20; /* Whitespace */
286 tc->screen[(tc->y_line * X_LINE_MAX) + tc->x_line] = (u16)((col << 12) | (0x00ff & c));
287 add_x_line(tc, 1);
288 }
289 }
290
text_buf_to_vram(TEXT_CTRL * tc)291 void text_buf_to_vram(TEXT_CTRL * tc)
292 {
293 int x_line, line_no;
294 int c;
295 u16 col;
296 LINE_BUF *lb;
297 TEXT_BUF *tb = &(tc->text_buf);
298
299
300 lb = tb->start;
301 put_char_vram(tc, '\f', (u16)0);
302
303 for (line_no = 0; line_no < (*tb->num_y + 1); line_no++)
304 {
305 x_line = 0;
306 if (lb == NULL)
307 break;
308 while (x_line < lb->last_count)
309 {
310 if (x_line >= (*tb->num_x + 1))
311 {
312 break;
313 }
314 else
315 {
316 c = lb->buf[x_line];
317 col = lb->col[x_line];
318 put_char_vram(tc, c, col);
319 }
320 x_line++;
321 }
322
323 #if 1
324 if (x_line <= *tb->num_x)
325 {
326 put_char_vram(tc, '\n', (u16)0);
327 }
328 #endif
329 lb = lb->next;
330 }
331
332 for (; line_no <= *tb->num_y; line_no++)
333 {
334 put_char_vram(tc, '\n', (u16)0);
335 }
336 }
337
338
mprintf(const char * text,...)339 void mprintf(const char *text, ...)
340 {
341 va_list vlist;
342 char temp[32];
343 s32 i = 0;
344 OSIntrMode enabled;
345
346 enabled = OS_DisableInterrupts();
347
348 va_start(vlist, text);
349 (void)OS_VSNPrintf(temp, 32, text, vlist);
350 va_end(vlist);
351
352 for (i = 0; i < 32; i++)
353 {
354 m_putchar(tc[0], (int)temp[i]);
355 if (temp[i] == NULL)
356 {
357 break;
358 }
359 }
360 #if 1
361 if (i >= 31)
362 m_putchar(tc[0], '\n');
363 #endif
364 (void)OS_RestoreInterrupts(enabled);
365
366
367 }
368
369 #if 0
370 0x42 0x6C 0x6F 0x63 0x6B 0x49 0x64 0x3D
371 0x31 0x30 0x30 0x30 0x31 0x20 0x73 0x69
372 0x7A 0x65 0x3D 0x36 0x35 0x35 0x33 0x36
373 0x0A 0x00
374 0x20 0x20 0x55 0x73 0x65 0x72 0x49 0x64
375 0x20 0x42 0x54 0x20 0x74 0x65 0x78 0x74
376 0x20 0x69 0x6E 0x66 0x6F 0x72 0x6D 0x61
377 0x74 0x69 0x6F 0x6E 0x20 0x61 0x72 0x00
378 0x20 0x20 0x00
379 0x42 0x6C 0x6F 0x63 0x6B 0x49 0x64 0x3D
380 0x31 0x30 0x30 0x30 0x32 0x20 0x73 0x69
381 0x7A 0x65 0x3D 0x36 0x35 0x35 0x33 0x36
382 0x0A 0x00
383 0x20 0x20 0x55 0x73 0x65 0x72 0x49 0x64
384 0x20 0x42 0x54 0x20 0x74 0x65 0x78 0x74
385 0x20 0x69 0x6E 0x66 0x6F 0x72 0x6D 0x61 0x74 0x69 0x6F 0x6E 0x20 0x61 0x72 0x00 0x3D 0x3E 0x00
386 #endif
mfprintf(TEXT_CTRL * tc,const char * text,...)387 void mfprintf(TEXT_CTRL * tc, const char *text, ...)
388 {
389 va_list vlist;
390
391 va_start(vlist, text);
392 mfvprintf(tc, text, vlist);
393 va_end(vlist);
394 }
395
mfvprintf(TEXT_CTRL * tc,const char * text,va_list va)396 void mfvprintf(TEXT_CTRL * tc, const char *text, va_list va)
397 {
398 OSIntrMode enabled;
399 char temp[32];
400 s32 i = 0;
401
402 enabled = OS_DisableInterrupts();
403
404 (void)OS_VSNPrintf(temp, 32, text, va);
405 for (i = 0; i < 32; i++)
406 {
407 m_putchar(tc, (int)temp[i]);
408 if (temp[i] == '\0')
409 {
410 break;
411 }
412 }
413 if (i >= 31)
414 m_putchar(tc, '\n');
415 (void)OS_RestoreInterrupts(enabled);
416 }
417