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