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