update DI disc code
[libogc.git] / libogc / console.c
blobd27bc77c37e0fc63fde4c3e2702a48d77fa06b83
1 #include <stdlib.h>
2 #include <string.h>
3 #include <reent.h>
4 #include <errno.h>
6 #include "asm.h"
7 #include "processor.h"
8 #include "color.h"
9 #include "cache.h"
10 #include "video.h"
11 #include "system.h"
13 #include "console.h"
14 #include "consol.h"
15 #include "usbgecko.h"
17 #include <stdio.h>
18 #include <sys/iosupport.h>
20 //---------------------------------------------------------------------------------
21 const devoptab_t dotab_stdout = {
22 //---------------------------------------------------------------------------------
23 "stdout", // device name
24 0, // size of file structure
25 NULL, // device open
26 NULL, // device close
27 __console_write, // device write
28 NULL, // device read
29 NULL, // device seek
30 NULL, // device fstat
31 NULL, // device stat
32 NULL, // device link
33 NULL, // device unlink
34 NULL, // device chdir
35 NULL, // device rename
36 NULL, // device mkdir
37 0, // dirStateSize
38 NULL, // device diropen_r
39 NULL, // device dirreset_r
40 NULL, // device dirnext_r
41 NULL, // device dirclose_r
42 NULL, // device statvfs_r
43 NULL, // device ftrunctate_r
44 NULL, // device fsync_r
45 NULL, // deviceData;
48 //color table
49 const unsigned int color_table[] =
51 0x00800080, // 30 normal black
52 0x246A24BE, // 31 normal red
53 0x4856484B, // 32 normal green
54 0x6D416D8A, // 33 normal yellow
55 0x0DBE0D75, // 34 normal blue
56 0x32A932B4, // 35 normal magenta
57 0x56955641, // 36 normal cyan
58 0xC580C580, // 37 normal white
59 0x7B807B80, // 30 bright black
60 0x4C544CFF, // 31 bright red
61 0x95299512, // 32 bright green
62 0xE200E294, // 33 bright yellow
63 0x1CFF1C6B, // 34 bright blue
64 0x69D669ED, // 35 bright magenta
65 0xB2ABB200, // 36 bright cyan
66 0xFF80FF80, // 37 bright white
69 static u32 do_xfb_copy = FALSE;
70 static struct _console_data_s stdcon;
71 static struct _console_data_s *curr_con = NULL;
72 static void *_console_buffer = NULL;
74 static s32 __gecko_status = -1;
75 static u32 __gecko_safe = 0;
77 extern u8 console_font_8x16[];
79 void __console_vipostcb(u32 retraceCnt)
81 u32 ycnt,xcnt, fb_stride;
82 u32 *fb,*ptr;
84 do_xfb_copy = TRUE;
86 ptr = curr_con->destbuffer;
87 fb = VIDEO_GetCurrentFramebuffer()+(curr_con->target_y*curr_con->tgt_stride) + curr_con->target_x*VI_DISPLAY_PIX_SZ;
88 fb_stride = curr_con->tgt_stride/4 - (curr_con->con_xres/VI_DISPLAY_PIX_SZ);
90 for(ycnt=curr_con->con_yres;ycnt>0;ycnt--)
92 for(xcnt=curr_con->con_xres;xcnt>0;xcnt-=VI_DISPLAY_PIX_SZ)
94 *fb++ = *ptr++;
96 fb += fb_stride;
99 do_xfb_copy = FALSE;
103 static void __console_drawc(int c)
105 console_data_s *con;
106 int ay;
107 unsigned int *ptr;
108 unsigned char *pbits;
109 unsigned char bits;
110 unsigned int color;
111 unsigned int fgcolor, bgcolor;
112 unsigned int nextline;
114 if(do_xfb_copy==TRUE) return;
115 if(!curr_con) return;
116 con = curr_con;
118 ptr = (unsigned int*)(con->destbuffer + ( con->con_stride * con->cursor_row * FONT_YSIZE ) + ((con->cursor_col * FONT_XSIZE / 2) * 4));
119 pbits = &con->font[c * FONT_YSIZE];
120 nextline = con->con_stride/4 - 4;
121 fgcolor = con->foreground;
122 bgcolor = con->background;
124 for (ay = 0; ay < FONT_YSIZE; ay++)
126 /* hard coded loop unrolling ! */
127 /* this depends on FONT_XSIZE = 8*/
128 #if FONT_XSIZE == 8
129 bits = *pbits++;
131 /* bits 1 & 2 */
132 if ( bits & 0x80)
133 color = fgcolor & 0xFFFF00FF;
134 else
135 color = bgcolor & 0xFFFF00FF;
136 if (bits & 0x40)
137 color |= fgcolor & 0x0000FF00;
138 else
139 color |= bgcolor & 0x0000FF00;
140 *ptr++ = color;
142 /* bits 3 & 4 */
143 if ( bits & 0x20)
144 color = fgcolor & 0xFFFF00FF;
145 else
146 color = bgcolor & 0xFFFF00FF;
147 if (bits & 0x10)
148 color |= fgcolor & 0x0000FF00;
149 else
150 color |= bgcolor & 0x0000FF00;
151 *ptr++ = color;
153 /* bits 5 & 6 */
154 if ( bits & 0x08)
155 color = fgcolor & 0xFFFF00FF;
156 else
157 color = bgcolor & 0xFFFF00FF;
158 if (bits & 0x04)
159 color |= fgcolor & 0x0000FF00;
160 else
161 color |= bgcolor & 0x0000FF00;
162 *ptr++ = color;
164 /* bits 7 & 8 */
165 if ( bits & 0x02)
166 color = fgcolor & 0xFFFF00FF;
167 else
168 color = bgcolor & 0xFFFF00FF;
169 if (bits & 0x01)
170 color |= fgcolor & 0x0000FF00;
171 else
172 color |= bgcolor & 0x0000FF00;
173 *ptr++ = color;
175 /* next line */
176 ptr += nextline;
177 #else
178 #endif
181 static void __console_clear_line( int line, int from, int to ) {
182 console_data_s *con;
183 unsigned int c;
184 unsigned int *p;
185 unsigned int x_pixels;
186 unsigned int px_per_col = FONT_XSIZE/2;
187 unsigned int line_height = FONT_YSIZE;
188 unsigned int line_width;
190 if( !(con = curr_con) ) return;
191 // For some reason there are xres/2 pixels per screen width
192 x_pixels = con->con_xres / 2;
194 line_width = (to - from)*px_per_col;
195 p = (unsigned int*)con->destbuffer;
197 // Move pointer to the current line and column offset
198 p += line*(FONT_YSIZE*x_pixels) + from*px_per_col;
200 // Clears 1 line of pixels at a time, line_height times
201 while( line_height-- ) {
202 c = line_width;
203 while( c-- )
204 *p++ = con->background;
205 p -= line_width;
206 p += x_pixels;
209 static void __console_clear(void)
211 console_data_s *con;
212 unsigned int c;
213 unsigned int *p;
215 if( !(con = curr_con) ) return;
217 c = (con->con_xres*con->con_yres)/2;
218 p = (unsigned int*)con->destbuffer;
220 while(c--)
221 *p++ = con->background;
223 con->cursor_row = 0;
224 con->cursor_col = 0;
225 con->saved_row = 0;
226 con->saved_col = 0;
228 static void __console_clear_from_cursor() {
229 console_data_s *con;
230 int cur_row;
232 if( !(con = curr_con) ) return;
233 cur_row = con->cursor_row;
235 __console_clear_line( cur_row, con->cursor_col, con->con_cols );
237 while( cur_row++ < con->con_rows )
238 __console_clear_line( cur_row, 0, con->con_cols );
241 static void __console_clear_to_cursor() {
242 console_data_s *con;
243 int cur_row;
245 if( !(con = curr_con) ) return;
246 cur_row = con->cursor_row;
248 __console_clear_line( cur_row, 0, con->cursor_col );
250 while( cur_row-- )
251 __console_clear_line( cur_row, 0, con->con_cols );
254 void __console_init(void *framebuffer,int xstart,int ystart,int xres,int yres,int stride)
256 unsigned int level;
257 console_data_s *con = &stdcon;
259 _CPU_ISR_Disable(level);
261 con->destbuffer = framebuffer;
262 con->con_xres = xres;
263 con->con_yres = yres;
264 con->con_cols = xres / FONT_XSIZE;
265 con->con_rows = yres / FONT_YSIZE;
266 con->con_stride = con->tgt_stride = stride;
267 con->target_x = xstart;
268 con->target_y = ystart;
270 con->font = console_font_8x16;
272 con->foreground = COLOR_WHITE;
273 con->background = COLOR_BLACK;
275 curr_con = con;
277 __console_clear();
279 devoptab_list[STD_OUT] = &dotab_stdout;
280 devoptab_list[STD_ERR] = &dotab_stdout;
281 _CPU_ISR_Restore(level);
283 setvbuf(stdout, NULL , _IONBF, 0);
284 setvbuf(stderr, NULL , _IONBF, 0);
287 void __console_init_ex(void *conbuffer,int tgt_xstart,int tgt_ystart,int tgt_stride,int con_xres,int con_yres,int con_stride)
289 unsigned int level;
290 console_data_s *con = &stdcon;
292 _CPU_ISR_Disable(level);
294 con->destbuffer = conbuffer;
295 con->target_x = tgt_xstart;
296 con->target_y = tgt_ystart;
297 con->con_xres = con_xres;
298 con->con_yres = con_yres;
299 con->tgt_stride = tgt_stride;
300 con->con_stride = con_stride;
301 con->con_cols = con_xres / FONT_XSIZE;
302 con->con_rows = con_yres / FONT_YSIZE;
303 con->cursor_row = 0;
304 con->cursor_col = 0;
305 con->saved_row = 0;
306 con->saved_col = 0;
308 con->font = console_font_8x16;
310 con->foreground = COLOR_WHITE;
311 con->background = COLOR_BLACK;
313 curr_con = con;
315 __console_clear();
317 devoptab_list[STD_OUT] = &dotab_stdout;
318 devoptab_list[STD_ERR] = &dotab_stdout;
320 VIDEO_SetPostRetraceCallback(__console_vipostcb);
322 _CPU_ISR_Restore(level);
324 setvbuf(stdout, NULL , _IONBF, 0);
325 setvbuf(stderr, NULL , _IONBF, 0);
328 static int __console_parse_escsequence(char *pchr)
330 char chr;
331 console_data_s *con;
332 int i;
333 int parameters[3];
334 int para;
336 if(!curr_con) return -1;
337 con = curr_con;
339 /* set default value */
340 para = 0;
341 parameters[0] = 0;
342 parameters[1] = 0;
343 parameters[2] = 0;
345 /* scan parameters */
346 i = 0;
347 chr = *pchr;
348 while( (para < 3) && (chr >= '0') && (chr <= '9') )
350 while( (chr >= '0') && (chr <= '9') )
352 /* parse parameter */
353 parameters[para] *= 10;
354 parameters[para] += chr - '0';
355 pchr++;
356 i++;
357 chr = *pchr;
359 para++;
361 if( *pchr == ';' )
363 /* skip parameter delimiter */
364 pchr++;
365 i++;
367 chr = *pchr;
370 /* get final character */
371 chr = *pchr++;
372 i++;
373 switch(chr)
375 /////////////////////////////////////////
376 // Cursor directional movement
377 /////////////////////////////////////////
378 case 'A':
380 curr_con->cursor_row -= parameters[0];
381 if(curr_con->cursor_row < 0) curr_con->cursor_row = 0;
382 break;
384 case 'B':
386 curr_con->cursor_row += parameters[0];
387 if(curr_con->cursor_row >= curr_con->con_rows) curr_con->cursor_row = curr_con->con_rows - 1;
388 break;
390 case 'C':
392 curr_con->cursor_col += parameters[0];
393 if(curr_con->cursor_col >= curr_con->con_cols) curr_con->cursor_col = curr_con->con_cols - 1;
394 break;
396 case 'D':
398 curr_con->cursor_col -= parameters[0];
399 if(curr_con->cursor_col < 0) curr_con->cursor_col = 0;
400 break;
402 /////////////////////////////////////////
403 // Cursor position movement
404 /////////////////////////////////////////
405 case 'H':
406 case 'f':
408 curr_con->cursor_col = parameters[1];
409 curr_con->cursor_row = parameters[0];
410 if(curr_con->cursor_row >= curr_con->con_rows) curr_con->cursor_row = curr_con->con_rows - 1;
411 if(curr_con->cursor_col >= curr_con->con_cols) curr_con->cursor_col = curr_con->con_cols - 1;
412 break;
414 /////////////////////////////////////////
415 // Screen clear
416 /////////////////////////////////////////
417 case 'J':
419 if( parameters[0] == 0 )
420 __console_clear_from_cursor();
421 if( parameters[0] == 1 )
422 __console_clear_to_cursor();
423 if( parameters[0] == 2 )
424 __console_clear();
426 break;
428 /////////////////////////////////////////
429 // Line clear
430 /////////////////////////////////////////
431 case 'K':
433 if( parameters[0] == 0 )
434 __console_clear_line( curr_con->cursor_row, curr_con->cursor_col, curr_con->con_cols );
435 if( parameters[0] == 1 )
436 __console_clear_line( curr_con->cursor_row, 0, curr_con->cursor_col );
437 if( parameters[0] == 2 )
438 __console_clear_line( curr_con->cursor_row, 0, curr_con->con_cols);
440 break;
442 /////////////////////////////////////////
443 // Save cursor position
444 /////////////////////////////////////////
445 case 's':
447 con->saved_col = con->cursor_col;
448 con->saved_row = con->cursor_row;
449 break;
451 /////////////////////////////////////////
452 // Load cursor position
453 /////////////////////////////////////////
454 case 'u':
455 con->cursor_col = con->saved_col;
456 con->cursor_row = con->saved_row;
457 break;
458 /////////////////////////////////////////
459 // SGR Select Graphic Rendition
460 /////////////////////////////////////////
461 case 'm':
463 // handle 30-37,39 for foreground color changes
464 if( (parameters[0] >= 30) && (parameters[0] <= 39) )
466 parameters[0] -= 30;
468 //39 is the reset code
469 if(parameters[0] == 9){
470 parameters[0] = 15;
472 else if(parameters[0] > 7){
473 parameters[0] = 7;
476 if(parameters[1] == 1)
478 // Intensity: Bold makes color bright
479 parameters[0] += 8;
481 con->foreground = color_table[parameters[0]];
483 // handle 40-47 for background color changes
484 else if( (parameters[0] >= 40) && (parameters[0] <= 47) )
486 parameters[0] -= 40;
488 if(parameters[1] == 1)
490 // Intensity: Bold makes color bright
491 parameters[0] += 8;
493 con->background = color_table[parameters[0]];
495 break;
499 return(i);
502 int __console_write(struct _reent *r,int fd,const char *ptr,size_t len)
504 size_t i = 0;
505 char *tmp = (char*)ptr;
506 console_data_s *con;
507 char chr;
509 if(__gecko_status>=0) {
510 if(__gecko_safe)
511 usb_sendbuffer_safe(__gecko_status,ptr,len);
512 else
513 usb_sendbuffer(__gecko_status,ptr,len);
516 if(!curr_con) return -1;
517 con = curr_con;
518 if(!tmp || len<=0) return -1;
520 i = 0;
521 while(*tmp!='\0' && i<len)
523 chr = *tmp++;
524 i++;
525 if ( (chr == 0x1b) && (*tmp == '[') )
527 /* escape sequence found */
528 int k;
530 tmp++;
531 i++;
532 k = __console_parse_escsequence(tmp);
533 tmp += k;
534 i += k;
536 else
538 switch(chr)
540 case '\n':
541 con->cursor_row++;
542 con->cursor_col = 0;
543 break;
544 case '\r':
545 con->cursor_col = 0;
546 break;
547 case '\b':
548 con->cursor_col--;
549 if(con->cursor_col < 0)
551 con->cursor_col = 0;
553 break;
554 case '\f':
555 con->cursor_row++;
556 break;
557 case '\t':
558 if(con->cursor_col%TAB_SIZE) con->cursor_col += (con->cursor_col%TAB_SIZE);
559 else con->cursor_col += TAB_SIZE;
560 break;
561 default:
562 __console_drawc(chr);
563 con->cursor_col++;
565 if( con->cursor_col >= con->con_cols)
567 /* if right border reached wrap around */
568 con->cursor_row++;
569 con->cursor_col = 0;
574 if( con->cursor_row >= con->con_rows)
576 /* if bottom border reached scroll */
577 memcpy(con->destbuffer,
578 con->destbuffer+con->con_stride*(FONT_YSIZE*FONT_YFACTOR+FONT_YGAP),
579 con->con_stride*con->con_yres-FONT_YSIZE);
581 unsigned int cnt = (con->con_stride * (FONT_YSIZE * FONT_YFACTOR + FONT_YGAP))/4;
582 unsigned int *ptr = (unsigned int*)(con->destbuffer + con->con_stride * (con->con_yres - FONT_YSIZE));
583 while(cnt--)
584 *ptr++ = con->background;
585 con->cursor_row--;
589 return i;
592 void CON_Init(void *framebuffer,int xstart,int ystart,int xres,int yres,int stride)
594 __console_init(framebuffer,xstart,ystart,xres,yres,stride);
597 s32 CON_InitEx(GXRModeObj *rmode, s32 conXOrigin,s32 conYOrigin,s32 conWidth,s32 conHeight)
599 VIDEO_SetPostRetraceCallback(NULL);
600 if(_console_buffer)
601 free(_console_buffer);
603 _console_buffer = malloc(conWidth*conHeight*VI_DISPLAY_PIX_SZ);
604 if(!_console_buffer) return -1;
606 __console_init_ex(_console_buffer,conXOrigin,conYOrigin,rmode->fbWidth*VI_DISPLAY_PIX_SZ,conWidth,conHeight,conWidth*VI_DISPLAY_PIX_SZ);
608 return 0;
611 void CON_GetMetrics(int *cols, int *rows)
613 if(curr_con) {
614 *cols = curr_con->con_cols;
615 *rows = curr_con->con_rows;
619 void CON_GetPosition(int *col, int *row)
621 if(curr_con) {
622 *col = curr_con->cursor_col;
623 *row = curr_con->cursor_row;
627 void CON_EnableGecko(int channel,int safe)
629 if(channel && (channel>1 || !usb_isgeckoalive(channel))) channel = -1;
631 __gecko_status = channel;
632 __gecko_safe = safe;
634 if(__gecko_status!=-1) {
635 devoptab_list[STD_OUT] = &dotab_stdout;
636 devoptab_list[STD_ERR] = &dotab_stdout;
638 // line buffered output for threaded apps when only using the usbgecko
639 if(!curr_con) {
640 setvbuf(stdout, NULL, _IOLBF, 0);
641 setvbuf(stderr, NULL, _IOLBF, 0);