18 #include <sys/iosupport.h>
20 //---------------------------------------------------------------------------------
21 const devoptab_t dotab_stdout
= {
22 //---------------------------------------------------------------------------------
23 "stdout", // device name
24 0, // size of file structure
27 __console_write
, // device write
33 NULL
, // device unlink
35 NULL
, // device rename
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
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
;
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
)
103 static void __console_drawc(int c
)
108 unsigned char *pbits
;
111 unsigned int fgcolor
, bgcolor
;
112 unsigned int nextline
;
114 if(do_xfb_copy
==TRUE
) return;
115 if(!curr_con
) return;
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*/
133 color
= fgcolor
& 0xFFFF00FF;
135 color
= bgcolor
& 0xFFFF00FF;
137 color
|= fgcolor
& 0x0000FF00;
139 color
|= bgcolor
& 0x0000FF00;
144 color
= fgcolor
& 0xFFFF00FF;
146 color
= bgcolor
& 0xFFFF00FF;
148 color
|= fgcolor
& 0x0000FF00;
150 color
|= bgcolor
& 0x0000FF00;
155 color
= fgcolor
& 0xFFFF00FF;
157 color
= bgcolor
& 0xFFFF00FF;
159 color
|= fgcolor
& 0x0000FF00;
161 color
|= bgcolor
& 0x0000FF00;
166 color
= fgcolor
& 0xFFFF00FF;
168 color
= bgcolor
& 0xFFFF00FF;
170 color
|= fgcolor
& 0x0000FF00;
172 color
|= bgcolor
& 0x0000FF00;
181 static void __console_clear_line( int line
, int from
, int to
) {
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
-- ) {
204 *p
++ = con
->background
;
209 static void __console_clear(void)
215 if( !(con
= curr_con
) ) return;
217 c
= (con
->con_xres
*con
->con_yres
)/2;
218 p
= (unsigned int*)con
->destbuffer
;
221 *p
++ = con
->background
;
228 static void __console_clear_from_cursor() {
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() {
245 if( !(con
= curr_con
) ) return;
246 cur_row
= con
->cursor_row
;
248 __console_clear_line( cur_row
, 0, con
->cursor_col
);
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
)
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
;
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
)
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
;
308 con
->font
= console_font_8x16
;
310 con
->foreground
= COLOR_WHITE
;
311 con
->background
= COLOR_BLACK
;
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
)
336 if(!curr_con
) return -1;
339 /* set default value */
345 /* scan parameters */
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';
363 /* skip parameter delimiter */
370 /* get final character */
375 /////////////////////////////////////////
376 // Cursor directional movement
377 /////////////////////////////////////////
380 curr_con
->cursor_row
-= parameters
[0];
381 if(curr_con
->cursor_row
< 0) curr_con
->cursor_row
= 0;
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;
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;
398 curr_con
->cursor_col
-= parameters
[0];
399 if(curr_con
->cursor_col
< 0) curr_con
->cursor_col
= 0;
402 /////////////////////////////////////////
403 // Cursor position movement
404 /////////////////////////////////////////
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;
414 /////////////////////////////////////////
416 /////////////////////////////////////////
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 )
428 /////////////////////////////////////////
430 /////////////////////////////////////////
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
);
442 /////////////////////////////////////////
443 // Save cursor position
444 /////////////////////////////////////////
447 con
->saved_col
= con
->cursor_col
;
448 con
->saved_row
= con
->cursor_row
;
451 /////////////////////////////////////////
452 // Load cursor position
453 /////////////////////////////////////////
455 con
->cursor_col
= con
->saved_col
;
456 con
->cursor_row
= con
->saved_row
;
458 /////////////////////////////////////////
459 // SGR Select Graphic Rendition
460 /////////////////////////////////////////
463 // handle 30-37,39 for foreground color changes
464 if( (parameters
[0] >= 30) && (parameters
[0] <= 39) )
468 //39 is the reset code
469 if(parameters
[0] == 9){
472 else if(parameters
[0] > 7){
476 if(parameters
[1] == 1)
478 // Intensity: Bold makes color bright
481 con
->foreground
= color_table
[parameters
[0]];
483 // handle 40-47 for background color changes
484 else if( (parameters
[0] >= 40) && (parameters
[0] <= 47) )
488 if(parameters
[1] == 1)
490 // Intensity: Bold makes color bright
493 con
->background
= color_table
[parameters
[0]];
502 int __console_write(struct _reent
*r
,int fd
,const char *ptr
,size_t len
)
505 char *tmp
= (char*)ptr
;
509 if(__gecko_status
>=0) {
511 usb_sendbuffer_safe(__gecko_status
,ptr
,len
);
513 usb_sendbuffer(__gecko_status
,ptr
,len
);
516 if(!curr_con
) return -1;
518 if(!tmp
|| len
<=0) return -1;
521 while(*tmp
!='\0' && i
<len
)
525 if ( (chr
== 0x1b) && (*tmp
== '[') )
527 /* escape sequence found */
532 k
= __console_parse_escsequence(tmp
);
549 if(con
->cursor_col
< 0)
558 if(con
->cursor_col
%TAB_SIZE
) con
->cursor_col
+= (con
->cursor_col
%TAB_SIZE
);
559 else con
->cursor_col
+= TAB_SIZE
;
562 __console_drawc(chr
);
565 if( con
->cursor_col
>= con
->con_cols
)
567 /* if right border reached wrap around */
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
));
584 *ptr
++ = con
->background
;
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
);
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
);
611 void CON_GetMetrics(int *cols
, int *rows
)
614 *cols
= curr_con
->con_cols
;
615 *rows
= curr_con
->con_rows
;
619 void CON_GetPosition(int *col
, int *row
)
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
;
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
640 setvbuf(stdout
, NULL
, _IOLBF
, 0);
641 setvbuf(stderr
, NULL
, _IOLBF
, 0);