1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - libraries - OS
3   File:     os_printf.c
4 
5   Copyright 2003-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:: 2009-09-17#$
14   $Rev: 11062 $
15   $Author: yada $
16  *---------------------------------------------------------------------------*/
17 #include        <nitro.h>
18 #include        <nitro/dbghost.h>
19 
20 //---------------- For IS-NITRO-DEBUGGER
21 #ifdef          SDK_LINK_ISD
22 # pragma warn_extracomma off
23 # include       <isdbglib.h>           // Has extra comma in enum
24 # pragma warn_extracomma reset
25 #else
26 void    ISDPrint(const char *);
27 #endif
28 
29 //---------------- For IS-TWL-DEBUGGER
30 #ifdef          SDK_LINK_ISTD
31 # pragma warn_extracomma off
32 # include       <istdbglib.h>          // Has extra comma in enum
33 # pragma warn_extracomma reset
34 #else
35 void    ISTDPrintEx(int console, const char *);
36 #endif
37 //---- Print output
38 #ifdef SDK_ARM9
39 #define OSi_PRINT_OUTPUT        (*(u8*)HW_PRINT_OUTPUT_ARM9)
40 #define OSi_PRINT_ERR_OUTPUT    (*(u8*)HW_PRINT_OUTPUT_ARM9ERR)
41 #else
42 #define OSi_PRINT_OUTPUT        (*(u8*)HW_PRINT_OUTPUT_ARM7)
43 #define OSi_PRINT_ERR_OUTPUT    (*(u8*)HW_PRINT_OUTPUT_ARM7ERR)
44 #endif
45 
46 #ifndef SDK_FINALROM
47 static char common_buffer[256];        // Thread unsafe, but less use of stack
48 #endif
49 
50 #if !defined(SDK_FINALROM) && defined(SDK_NO_MESSAGE)
51 #undef OSi_Warning
52 #undef OSi_TWarning
53 #undef OSi_Panic
54 #undef OSi_TPanic
55 void    OSi_Warning(const char *file, int line, const char *fmt, ...);
56 void    OSi_TWarning(const char *file, int line, const char *fmt, ...);
57 void    OSi_Panic(const char *file, int line, const char *fmt, ...);
58 void    OSi_TPanic(const char *file, int line, const char *fmt, ...);
59 #endif /* SDK_NO_MESSAGE */
60 
61 
62 /*---------------------------------------------------------------------------*
63   Name:         OS_PutChar
64                 OS_FPutChar
65 
66   Description:  Puts a letter for debug console.
67 
68   Arguments:    console: Output window
69                 c: Char code, should be 0x01-0xff
70 
71   Returns:      None.
72  *---------------------------------------------------------------------------*/
73 #ifndef SDK_FINALROM
OS_PutChar(char c)74 SDK_WEAK_SYMBOL void OS_PutChar(char c)
75 {
76 	OS_FPutChar((int)OSi_PRINT_OUTPUT, c);
77 }
78 
OS_FPutChar(int console,char c)79 SDK_WEAK_SYMBOL void OS_FPutChar(int console, char c)
80 {
81     char    str[2];
82 
83     str[0] = c;
84     str[1] = '\0';
85 
86     // Because of no putchar-type function on ISDebugger library,
87     // use 'putstring' for a single letter outputting
88     OS_FPutString(console, str);
89 }
90 #endif
91 
92 /*---------------------------------------------------------------------------*
93   Name:         OS_FPutString
94 
95   Description:  put a string to debug console.
96                 console port are automatically switched depends on emu/hw
97 
98   Arguments:    console : output window
99                 str: String
100 
101   Returns:      None.
102  *---------------------------------------------------------------------------*/
103 static void OS_PutStringDefault(const char* str);
104 static void OS_FPutStringInit(int console, const char *str);
105 
106 #ifndef SDK_FINALROM
107 static void OS_FPutStringDummy(int console, const char *str);
108 static void OS_FPutStringAris(int console, const char *str);
109 static void OS_FPutStringISD(int console, const char *str);
110 static void OS_FPutStringISTD(int console, const char *str);
111 #ifdef  SDK_ARM7
112 static void OS_FPutStringPrnSrv(int console, const char *str);
113 #endif
114 #endif
115 
116 #ifndef SDK_FINALROM
117 void    (*OS_PutString)  (const char *str) = OS_PutStringDefault;
118 void    (*OS_FPutString) (int console, const char *str) = OS_FPutStringInit;
119 void    (*OSi_FuncTerminate) (void) = OS_Terminate;
120 //----  Hook function
121 static OSFPutStringHookType  OSi_FPutStringHook = NULL;
122 #endif
123 
124 
125 /*---------------------------------------------------------------------------*
126   Name:         OS_PutStringDefault
127   Description:  OS_PutString initializer
128  *---------------------------------------------------------------------------*/
OS_PutStringDefault(const char * str)129 static void OS_PutStringDefault(const char* str)
130 {
131 #pragma unused(str)
132 #ifndef SDK_FINALROM
133     OS_FPutString(OS_PRINT_OUTPUT_CURRENT, str);
134 #endif
135 }
136 
137 /*---------------------------------------------------------------------------*
138   Name:         OS_FPutStringInit
139   Description:  OS_FPutString initializer
140  *---------------------------------------------------------------------------*/
OS_FPutStringInit(int console,const char * str)141 static void OS_FPutStringInit(int console, const char *str)
142 {
143 #ifndef SDK_FINALROM
144     OSIntrMode intr = OS_DisableInterrupts();
145 	u32 consoleType = OS_GetConsoleType();
146 
147     OS_FPutString = OS_FPutStringDummy;
148 
149 #ifdef  SDK_ARM9
150 	//---- ARM9
151     if ( consoleType & OS_CONSOLE_ENSATA )
152     {
153         OS_FPutString = OS_FPutStringAris;
154     }
155     else if ( consoleType & OS_CONSOLE_TWLDEBUGGER )
156 	{
157 		OS_FPutString = OS_FPutStringISTD;
158 	}
159 	else if ( consoleType & OS_CONSOLE_ISDEBUGGER )
160 	{
161 #ifndef SDK_TWLLTD
162 		OS_FPutString = OS_FPutStringISD;
163 #endif
164 	}
165 #else
166 	//---- ARM7
167     if ( (OSPrintServerBuffer *)PXI_GetComponentParam() != NULL )
168     {
169         OS_FPutString = OS_FPutStringPrnSrv;
170     }
171     else
172     {
173         if ( consoleType & OS_CONSOLE_TWLDEBUGGER )
174         {
175             OS_FPutString = OS_FPutStringISTD;
176         }
177     }
178 #endif
179 
180     OS_FPutString(console, str);
181 
182     (void)OS_RestoreInterrupts(intr);
183 
184 #else
185 #pragma unused(console, str)
186 #endif
187 }
188 
189 /*---------------------------------------------------------------------------*
190   Name:         OS_FPutStringDummy
191   Description:  dummy OS_FPutString. do nothing.
192  *---------------------------------------------------------------------------*/
OS_FPutStringDummy(int console,const char * str)193 static void OS_FPutStringDummy(int console, const char *str)
194 {
195 #pragma unused(console, str)
196 #ifndef SDK_FINALROM
197 	if ( OSi_FPutStringHook )
198 	{
199 		OSi_FPutStringHook(OS_FPUTSTRING_DUMMY, console, str);
200 	}
201 #endif
202 }
203 
204 /*---------------------------------------------------------------------------*
205   Name:         OS_FPutStringAris
206   Description:  OS_FPutString for software simulator called ARIS
207  *---------------------------------------------------------------------------*/
208 #ifndef SDK_FINALROM
209 #ifdef  SDK_CW_WARNOFF_SAFESTRB
210 #include <nitro/code32.h>
211 #endif
OS_FPutStringAris(int console,const char * str)212 static void OS_FPutStringAris(int console, const char *str)
213 {
214     char    c;
215 
216 	if ( console == OS_PRINT_OUTPUT_CURRENT )
217 	{
218 		console = (int)OSi_PRINT_OUTPUT;
219 	}
220 	else if ( console == OS_PRINT_OUTPUT_ERROR )
221 	{
222 		console = (int)OSi_PRINT_ERR_OUTPUT;
223 	}
224 
225 	if ( console != OS_PRINT_OUTPUT_NONE )
226 	{
227 		while ('\0' != (c = *str))
228 		{
229 			reg_OS_EMU_CONSOLE_OUT = (u8)c; // Console out
230 			str++;
231 		}
232 		if ( OSi_FPutStringHook )
233 		{
234 			OSi_FPutStringHook(OS_FPUTSTRING_ARIS, console, str);
235 		}
236 	}
237 }
238 #ifdef  SDK_CW_WARNOFF_SAFESTRB
239 #include <nitro/codereset.h>
240 #endif
241 #endif
242 
243 /*---------------------------------------------------------------------------*
244   Name:         OS_FPutStringISD
245   Description:  OS_FPutString for hardware emulator called IS Debugger
246  *---------------------------------------------------------------------------*/
247 #ifndef SDK_FINALROM
OS_FPutStringISD(int console,const char * str)248 static void OS_FPutStringISD(int console, const char *str)
249 {
250     // ISDPrint initialize process
251     OS_InitLock();
252 
253 	if ( console == OS_PRINT_OUTPUT_CURRENT )
254 	{
255 		console = (int)OSi_PRINT_OUTPUT;
256 	}
257 	else if ( console == OS_PRINT_OUTPUT_ERROR )
258 	{
259 		console = (int)OSi_PRINT_ERR_OUTPUT;
260 	}
261 
262 	if ( console != OS_PRINT_OUTPUT_NONE )
263 	{
264 		ISDPrint(str);
265 		if ( OSi_FPutStringHook )
266 		{
267 			OSi_FPutStringHook(OS_FPUTSTRING_ISD, console, str);
268 		}
269 	}
270 }
271 #endif
272 
273 /*---------------------------------------------------------------------------*
274   Name:         OS_FPutStringISTD
275   Description:  OS_FPutString for hardware emulator called IS TWL Debugger
276  *---------------------------------------------------------------------------*/
277 #ifndef SDK_FINALROM
OS_FPutStringISTD(int console,const char * str)278 static void OS_FPutStringISTD(int console, const char *str)
279 {
280     // ISTDPrintEx initialize process
281     OS_InitLock();
282 
283 	if ( console == OS_PRINT_OUTPUT_CURRENT )
284 	{
285 		console = (int)OSi_PRINT_OUTPUT;
286 	}
287 	else if ( console == OS_PRINT_OUTPUT_ERROR )
288 	{
289 		console = (int)OSi_PRINT_ERR_OUTPUT;
290 	}
291 
292 	if ( console != OS_PRINT_OUTPUT_NONE )
293 	{
294 		ISTDPrintEx(console, str);
295 		if ( OSi_FPutStringHook )
296 		{
297 			OSi_FPutStringHook(OS_FPUTSTRING_ISTD, console, str);
298 		}
299 	}
300 }
301 #endif
302 
303 
304 /*---------------------------------------------------------------------------*
305   Name:         OS_VPrintf/OS_TVPrintf
306 
307   Description:  Prints formatted strings (vprintf version).
308 
309   Arguments:    fmt: Format string
310                 vlist: Parameters
311 
312   Returns:      None.
313  *---------------------------------------------------------------------------*/
314 // If you want to use "vsnprintf()" in ARM7, define SDK_USE_VSNPRINTF.
315 // "vsnprintf()" is able to print float format but the code size become hugely bigger.
316 // #define SDK_USE_VSNPRINTF
317 
318 #ifndef SDK_FINALROM
319 #if     defined(SDK_ARM9) || defined(SDK_USE_VSNPRINTF)
OS_VPrintf(const char * fmt,va_list vlist)320 SDK_WEAK_SYMBOL void OS_VPrintf(const char *fmt, va_list vlist)
321 {
322 	OS_VFPrintf(OS_PRINT_OUTPUT_CURRENT, fmt, vlist);
323 }
OS_VFPrintf(int console,const char * fmt,va_list vlist)324 SDK_WEAK_SYMBOL void OS_VFPrintf(int console, const char *fmt, va_list vlist)
325 {
326     (void)vsnprintf(common_buffer, sizeof(common_buffer), fmt, vlist);
327     OS_FPutString(console, common_buffer);
328 }
329 #else
OS_VPrintf(const char * fmt,va_list vlist)330 SDK_WEAK_SYMBOL void OS_VPrintf(const char *fmt, va_list vlist)
331 {
332     OS_TVFPrintf(OS_PRINT_OUTPUT_CURRENT, fmt, vlist);
333 }
OS_VFPrintf(int console,const char * fmt,va_list vlist)334 SDK_WEAK_SYMBOL void OS_VFPrintf(int console, const char *fmt, va_list vlist)
335 {
336     OS_TVFPrintf(console, fmt, vlist);
337 }
338 #endif
OS_TVPrintf(const char * fmt,va_list vlist)339 SDK_WEAK_SYMBOL void OS_TVPrintf(const char *fmt, va_list vlist)
340 {
341 	OS_TVFPrintf(OS_PRINT_OUTPUT_CURRENT, fmt, vlist);
342 }
OS_TVFPrintf(int console,const char * fmt,va_list vlist)343 SDK_WEAK_SYMBOL void OS_TVFPrintf(int console, const char *fmt, va_list vlist)
344 {
345     (void)OS_VSNPrintf(common_buffer, sizeof(common_buffer), fmt, vlist);
346     OS_FPutString(console, common_buffer);
347 }
OS_TVPrintfEx(const char * fmt,va_list vlist)348 SDK_WEAK_SYMBOL void OS_TVPrintfEx(const char *fmt, va_list vlist)
349 {
350 	OS_TVFPrintfEx(OS_PRINT_OUTPUT_CURRENT, fmt, vlist);
351 }
OS_TVFPrintfEx(int console,const char * fmt,va_list vlist)352 SDK_WEAK_SYMBOL void OS_TVFPrintfEx(int console, const char *fmt, va_list vlist)
353 {
354     (void)OS_VSNPrintfEx(common_buffer, sizeof(common_buffer), fmt, vlist);
355     OS_FPutString(console, common_buffer);
356 }
357 #endif
358 
359 /*---------------------------------------------------------------------------*
360   Name:         OS_Printf/OS_TPrintf/OS_TPrintfEx
361                 OS_FPrintf/OS_TFPrintf/OS_TFPrintfEx
362 
363   Description:  Prints formatted strings.
364 
365   Arguments:    console: Output window
366                 fmt: Format string
367                 ...   and parameters
368 
369   Returns:      None.
370  *---------------------------------------------------------------------------*/
371 #ifndef SDK_FINALROM
OS_Printf(const char * fmt,...)372 SDK_WEAK_SYMBOL void OS_Printf(const char *fmt, ...)
373 {
374     va_list vlist;
375 
376     va_start(vlist, fmt);
377     OS_VFPrintf(OS_PRINT_OUTPUT_CURRENT, fmt, vlist);
378     va_end(vlist);
379 }
380 
OS_FPrintf(int console,const char * fmt,...)381 SDK_WEAK_SYMBOL void OS_FPrintf(int console, const char *fmt, ...)
382 {
383     va_list vlist;
384 
385     va_start(vlist, fmt);
386     OS_VFPrintf(console, fmt, vlist);
387     va_end(vlist);
388 }
389 
OS_TPrintf(const char * fmt,...)390 SDK_WEAK_SYMBOL void OS_TPrintf(const char *fmt, ...)
391 {
392     va_list vlist;
393 
394     va_start(vlist, fmt);
395     OS_TVFPrintf(OS_PRINT_OUTPUT_CURRENT, fmt, vlist);
396     va_end(vlist);
397 }
398 
OS_TFPrintf(int console,const char * fmt,...)399 SDK_WEAK_SYMBOL void OS_TFPrintf(int console, const char *fmt, ...)
400 {
401     va_list vlist;
402 
403     va_start(vlist, fmt);
404     OS_TVFPrintf(console, fmt, vlist);
405     va_end(vlist);
406 }
407 
OS_TPrintfEx(const char * fmt,...)408 SDK_WEAK_SYMBOL void OS_TPrintfEx(const char *fmt, ...)
409 {
410     va_list vlist;
411 
412     va_start(vlist, fmt);
413     OS_TVFPrintfEx(OS_PRINT_OUTPUT_CURRENT, fmt, vlist);
414     va_end(vlist);
415 }
416 
OS_TFPrintfEx(int console,const char * fmt,...)417 SDK_WEAK_SYMBOL void OS_TFPrintfEx(int console, const char *fmt, ...)
418 {
419     va_list vlist;
420 
421     va_start(vlist, fmt);
422     OS_TVFPrintfEx(console, fmt, vlist);
423     va_end(vlist);
424 }
425 #endif
426 
427 
428 /*---------------------------------------------------------------------------*
429   Name:         OSi_Warning / OSi_TWarning
430 
431   Description:  Prints warning message.
432 
433   Arguments:    file: Filename of warning location
434                 line: Line number of warning location
435                 fmt: Format string
436                 ...   and parameters
437 
438   Returns:      None.
439  *---------------------------------------------------------------------------*/
440 #ifndef SDK_FINALROM
OSi_Warning(const char * file,int line,const char * fmt,...)441 SDK_WEAK_SYMBOL void OSi_Warning(const char *file, int line, const char *fmt, ...)
442 {
443     va_list vlist;
444 
445     va_start(vlist, fmt);
446     OS_FPrintf(OS_PRINT_OUTPUT_ERROR, "%s:%d Warning:", file, line);
447     OS_VFPrintf(OS_PRINT_OUTPUT_ERROR, fmt, vlist);
448     OS_FPrintf(OS_PRINT_OUTPUT_ERROR, "\n");
449     va_end(vlist);
450 }
451 
452 
OSi_TWarning(const char * file,int line,const char * fmt,...)453 SDK_WEAK_SYMBOL void OSi_TWarning(const char *file, int line, const char *fmt, ...)
454 {
455     va_list vlist;
456 
457     va_start(vlist, fmt);
458     OS_TPrintf("%s:%d Warning:", file, line);
459     OS_TVPrintf(fmt, vlist);
460     OS_TPrintf("\n");
461     va_end(vlist);
462 }
463 #endif
464 
465 /*---------------------------------------------------------------------------*
466   Name:         OSi_Panic/OSi_TPanic
467 
468   Description:  Prints panic message and halt CPU.
469 
470   Arguments:    file: Filename of panic location
471                 line: Line number of panic location
472                 fmt: Format string
473                 ...   and parameters
474 
475   Returns:      None.
476  *---------------------------------------------------------------------------*/
477 #ifndef SDK_FINALROM
OSi_Panic(const char * file,int line,const char * fmt,...)478 SDK_WEAK_SYMBOL void OSi_Panic(const char *file, int line, const char *fmt, ...)
479 {
480     va_list vlist;
481 
482     va_start(vlist, fmt);
483     (void)OS_DisableInterrupts();
484     OS_FPrintf(OS_PRINT_OUTPUT_ERROR, "%s:%d Panic:", file, line);
485     OS_VFPrintf(OS_PRINT_OUTPUT_ERROR, fmt, vlist);
486     OS_FPrintf(OS_PRINT_OUTPUT_ERROR, "\n");
487     OSi_FuncTerminate();               // Never Returns
488 }
489 
OSi_TPanic(const char * file,int line,const char * fmt,...)490 SDK_WEAK_SYMBOL void OSi_TPanic(const char *file, int line, const char *fmt, ...)
491 {
492     va_list vlist;
493 
494     va_start(vlist, fmt);
495     (void)OS_DisableInterrupts();
496     OS_TPrintf("%s:%d Panic:", file, line);
497     OS_TVPrintf(fmt, vlist);
498     OS_TPrintf("\n");
499     OSi_FuncTerminate();               // Never Returns
500 }
501 #endif
502 
503 /*---------------------------------------------------------------------------*
504   Name:         OSi_FWarning / OSi_TFWarning
505 
506   Description:  Prints warning message.
507 
508   Arguments:    console: Output window
509                 file: Filename of warning location
510                 line: Line number of warning location
511                 fmt: Format string
512                 ...   and parameters
513 
514   Returns:      None.
515  *---------------------------------------------------------------------------*/
516 #ifndef SDK_FINALROM
OSi_FWarning(int console,const char * file,int line,const char * fmt,...)517 SDK_WEAK_SYMBOL void OSi_FWarning(int console, const char *file, int line, const char *fmt, ...)
518 {
519     va_list vlist;
520 
521     va_start(vlist, fmt);
522     OS_FPrintf(console, "%s:%d Warning:", file, line);
523     OS_VFPrintf(console, fmt, vlist);
524     OS_FPrintf(console, "\n");
525     va_end(vlist);
526 }
527 
528 
OSi_TFWarning(int console,const char * file,int line,const char * fmt,...)529 SDK_WEAK_SYMBOL void OSi_TFWarning(int console, const char *file, int line, const char *fmt, ...)
530 {
531     va_list vlist;
532 
533     va_start(vlist, fmt);
534     OS_TFPrintf(console, "%s:%d Warning:", file, line);
535     OS_TVFPrintf(console, fmt, vlist);
536     OS_TFPrintf(console, "\n");
537     va_end(vlist);
538 }
539 #endif
540 
541 /*---------------------------------------------------------------------------*
542   Name:         OSi_FPanic/OSi_TFPanic
543 
544   Description:  Prints panic message and halts CPU.
545 
546   Arguments:    file: Filename of panic location
547                 line: Line number of panic location
548                 fmt: Format string
549                 ...   and parameters
550 
551   Returns:      None.
552  *---------------------------------------------------------------------------*/
553 #ifndef SDK_FINALROM
OSi_FPanic(int console,const char * file,int line,const char * fmt,...)554 SDK_WEAK_SYMBOL void OSi_FPanic(int console, const char *file, int line, const char *fmt, ...)
555 {
556     va_list vlist;
557 
558     va_start(vlist, fmt);
559     (void)OS_DisableInterrupts();
560     OS_FPrintf(console, "%s:%d Panic:", file, line);
561     OS_VFPrintf(console, fmt, vlist);
562     OS_FPrintf(console, "\n");
563     OSi_FuncTerminate();               // Never Returns
564 }
565 
OSi_TFPanic(int console,const char * file,int line,const char * fmt,...)566 SDK_WEAK_SYMBOL void OSi_TFPanic(int console, const char *file, int line, const char *fmt, ...)
567 {
568     va_list vlist;
569 
570     va_start(vlist, fmt);
571     (void)OS_DisableInterrupts();
572     OS_TFPrintf(console, "%s:%d Panic:", file, line);
573     OS_TVFPrintf(console, fmt, vlist);
574     OS_TFPrintf(console, "\n");
575     OSi_FuncTerminate();               // Never Returns
576 }
577 #endif
578 
579 /*---------------------------------------------------------------------------*
580   Name:         OS_InitPrintServer
581 
582   Description:  Initializes print server.
583                 - This code should be called before OS_InitLock()
584                 - OS_InitLock() are also called from OS_Init()
585 
586   Arguments:    None.
587 
588   Returns:      None.
589  *---------------------------------------------------------------------------*/
590 #ifdef   SDK_ARM9
591 #ifndef  SDK_FINALROM
OS_InitPrintServer(void)592 void OS_InitPrintServer(void)
593 {
594     OSPrintServerBuffer *p;
595 
596     // First, allocate buffer and register it.
597     OS_InitArena();
598     p = OS_AllocFromSharedArenaHi(sizeof(OSPrintServerBuffer), 4);
599     p->in = p->out = 0UL;
600     PXI_SetComponentParam((u32)p);
601 }
602 #endif //SDK_FINALROM
603 #endif //SDK_ARM9
604 
605 
606 /*---------------------------------------------------------------------------*
607   Name:         OS_PrintServer
608 
609   Description:  Prints a string comes from ARM7 via shared memory.
610 
611   Arguments:    str: String
612 
613   Returns:      None.
614  *---------------------------------------------------------------------------*/
615 #ifdef   SDK_ARM9
616 #ifndef  SDK_FINALROM
617 #include <nitro/code32.h>              // To access 'common_buffer' via cache
OS_PrintServer(void)618 void OS_PrintServer(void)
619 {
620     OSPrintServerBuffer *p;
621     register OSPrintWChar word;
622 
623     u32     in, out;
624     int     i;
625 
626     p = (OSPrintServerBuffer *)PXI_GetComponentParam();
627 
628     //---- If print buffer isn't set up, do nothing.
629     if (!p)
630     {
631         return;
632     }
633 
634     out = p->out;
635     in = p->in;
636 
637     while (in != out)
638     {
639         i = 0;
640 
641         while (in != out && i < sizeof(common_buffer) - 3)
642         {
643             word.s = p->buffer[out].s;
644             if (word.c[0])
645             {
646                 common_buffer[i++] = word.c[0]; // store via cache
647 
648                 if (word.c[1])
649                 {
650                     common_buffer[i++] = word.c[1];     // store via cache
651                 }
652             }
653             out++;
654             if (out >= OS_PRINTSRV_WCHARSIZE)
655                 out = 0;
656         }
657         common_buffer[i] = '\0';       // store via cache
658         OS_FPutString(OS_PRINT_OUTPUT_CURRENT, common_buffer);
659     }
660 
661     // tell finished
662     p->out = out;
663 }
664 
665 #include <nitro/codereset.h>
666 #endif //SDK_FINALROM
667 #endif //SDK_ARM9
668 
669 
670 /*---------------------------------------------------------------------------*
671   Name:         OS_FPutStringPrnSrv
672 
673   Description:  Sends string to ARM9 via shared memory.
674 
675   Arguments:    console: Output window
676                 str: String to be sent
677 
678   Returns:      None.
679  *---------------------------------------------------------------------------*/
680 #ifdef  SDK_ARM7
OS_FPutStringPrnSrv(int console,const char * str)681 static void OS_FPutStringPrnSrv(int console, const char *str)
682 {
683 #pragma unused(console, str)
684 #ifndef  SDK_FINALROM
685     OSPrintServerBuffer *p;
686     register OSPrintWChar word;
687 
688     u32     in, in_tmp, out;
689     u32     isOdd;
690 
691 	if ( console == OS_PRINT_OUTPUT_NONE )
692 	{
693 		return;
694 	}
695 
696     p = (OSPrintServerBuffer *)PXI_GetComponentParam();
697     in = p->in;
698     out = p->out;
699     isOdd = ((u32)str) & 1;
700 
701     while (1)
702     {
703         in_tmp = in + 1;
704         if (in_tmp >= OS_PRINTSRV_WCHARSIZE)
705             in_tmp = 0;
706         if (out == in_tmp)
707             break;                     // Buffer full, then exit
708 
709         if (isOdd)
710         {
711             p->buffer[in].s = word.s = (u16)((*(u16 *)(str - 1)) & 0xff00);
712             str++;
713             isOdd = 0UL;
714             if (!word.c[1])
715                 break;
716             in = in_tmp;
717         }
718         else
719         {
720             p->buffer[in].s = word.s = *(u16 *)str;
721             str += 2;
722             if (!word.c[0])
723                 break;
724             in = in_tmp;
725             if (!word.c[1])
726                 break;
727         }
728     }
729     p->in = in;
730 #endif //SDK_FINALROM
731 }
732 #endif //SDK_ARM7
733 
734 
735 #if defined(SDK_CW_WARNOFF_SAFESTRB)
736 #include <nitro/code32.h>
737 #endif
738 
739 /* inner function for sized-buffer output */
740 typedef struct dst_string_tag
741 {
742     size_t  len;
743     char   *cur;
744     char   *base;
745 }
746 dst_string;
747 
string_put_char(dst_string * p,char c)748 static void string_put_char(dst_string * p, char c)
749 {
750     if (p->len > 0)
751         *p->cur = c, --p->len;
752     ++p->cur;
753 }
754 
string_fill_char(dst_string * p,char c,int n)755 static void string_fill_char(dst_string * p, char c, int n)
756 {
757     if (n > 0)
758     {
759         size_t  i, k = p->len;
760         if (k > (size_t) n)
761             k = (size_t) n;
762         for (i = 0; i < k; ++i)
763             p->cur[i] = c;
764         p->len -= k;
765         p->cur += n;
766     }
767 }
768 
string_put_string(dst_string * p,const char * s,int n)769 static void string_put_string(dst_string * p, const char *s, int n)
770 {
771     if (n > 0)
772     {
773         size_t  i, k = p->len;
774         if (k > (size_t) n)
775             k = (size_t) n;
776         for (i = 0; i < k; ++i)
777             p->cur[i] = s[i];
778         p->len -= k;
779         p->cur += n;
780     }
781 }
782 
783 /*---------------------------------------------------------------------------*
784   Name:         OS_SPrintf
785 
786   Description:  Equal to 'OS_VSPrintf' except argument style.
787 
788   Arguments:    dst: Destination buffer
789                 fmt: Format string
790 
791   Returns:      Length of the generated string.
792  *---------------------------------------------------------------------------*/
OS_SPrintf(char * dst,const char * fmt,...)793 SDK_WEAK_SYMBOL int OS_SPrintf(char *dst, const char *fmt, ...)
794 {
795     int     ret;
796     va_list va;
797     va_start(va, fmt);
798     ret = OS_VSPrintf(dst, fmt, va);
799     va_end(va);
800     return ret;
801 }
802 
803 /*---------------------------------------------------------------------------*
804   Name:         OS_VSPrintf
805 
806   Description:  Equal to 'OS_VSNPrintf' except buffer size argument.
807 
808   Arguments:    dst: Destination buffer
809                 fmt: Format string
810                 vlist: Parameters
811 
812   Returns:      Length of the generated string.
813  *---------------------------------------------------------------------------*/
OS_VSPrintf(char * dst,const char * fmt,va_list vlist)814 SDK_WEAK_SYMBOL int OS_VSPrintf(char *dst, const char *fmt, va_list vlist)
815 {
816     return OS_VSNPrintf(dst, 0x7FFFFFFF, fmt, vlist);
817 }
818 
819 /*---------------------------------------------------------------------------*
820   Name:         OS_SNPrintf
821 
822   Description:  Equal to 'OS_VSNPrintf' except argument style.
823 
824   Arguments:    dst: Destination buffer
825                 len: Destination buffer size
826                 fmt: Format string
827 
828   Returns:      Length of the generated string (except '\0').
829                 if(result < len),
830                   put NUL in dst[result].
831                 else if(len > 0),
832                   put NUL in dst[len - 1].
833                 else,
834                   do nothing.
835  *---------------------------------------------------------------------------*/
OS_SNPrintf(char * dst,size_t len,const char * fmt,...)836 SDK_WEAK_SYMBOL int OS_SNPrintf(char *dst, size_t len, const char *fmt, ...)
837 {
838     int     ret;
839     va_list va;
840     va_start(va, fmt);
841     ret = OS_VSNPrintf(dst, len, fmt, va);
842     va_end(va);
843     return ret;
844 }
845 
846 /*---------------------------------------------------------------------------*
847   Name:         OS_VSNPrintf
848 
849   Description:  small-size vsnprintf which is similar to 'vsnprintf'
850                 without following supports.
851                 * CodeWarrior Extensions (#s)
852                 * MSL AltiVec Extensions (v, vh, vl, hv, lv, @)
853                 * indexed argments (%m$, *m$)
854                 * floating-point
855                 * wchar_t
856 
857   Note:         '+' and '#' do not work, MSL's sprintf().
858                 to keep same result, they are no implement.
859                 { // example
860                   char buf[5];
861                   sprintf(buf, "%-i\n", 45);  // "45"  (OK)
862                   sprintf(buf, "%0i\n", 45);  // "45"  (OK)
863                   sprintf(buf, "% i\n", 45);  // " 45" (OK)
864                   sprintf(buf, "%+i\n", 45);  // "%+i" ("+45" expected)
865                   sprintf(buf, "%#x\n", 45);  // "%#x" ("0x2d" expected)
866                   // but, this works correctly!
867                   sprintf(buf, "% +i\n", 45); // "+45" (OK)
868                 }
869 
870   Arguments:    dst: Destination buffer
871                 len: Destination buffer size
872                 fmt: Format string
873                 vlist: Parameters
874 
875   Returns:      Length of the generated string (except '\0').
876                 if(result < len),
877                   put NUL in dst[result].
878                 else if(len > 0),
879                   put NUL in dst[len - 1].
880                 else,
881                   do nothing.
882  *---------------------------------------------------------------------------*/
OS_VSNPrintf(char * dst,size_t len,const char * fmt,va_list vlist)883 SDK_WEAK_SYMBOL int OS_VSNPrintf(char *dst, size_t len, const char *fmt, va_list vlist)
884 {
885     return STD_TVSNPrintf(dst, len, fmt, vlist);
886 }
887 
888 /*---------------------------------------------------------------------------*
889   Name:         OS_VSNPrintfEx
890 
891   Description:  OS_VSNPrintfEx is an addition of binary output to OS_VSNPrintfEx.
892 
893   Arguments:    dst: Destination buffer
894                 len: Destination buffer size
895                 fmt: Format string
896                 vlist: Parameters
897 
898   Returns:      Length of the generated string (except '\0').
899                 if(result < len),
900                   put NUL in dst[result].
901                 else if(len > 0),
902                   put NUL in dst[len - 1].
903                 else,
904                   do nothing.
905  *---------------------------------------------------------------------------*/
OS_VSNPrintfEx(char * dst,size_t len,const char * fmt,va_list vlist)906 SDK_WEAK_SYMBOL int OS_VSNPrintfEx(char *dst, size_t len, const char *fmt, va_list vlist)
907 {
908     char    buf[24];
909     int     n_buf;
910     char    prefix[2];
911     int     n_prefix;
912 
913     const char *s = fmt;
914 
915     dst_string str;
916     str.len = len, str.cur = str.base = dst;
917 
918     while (*s)
919     {
920         if ((unsigned int)(((unsigned char)*s ^ 0x20) - 0xA1) < 0x3C)
921         {
922             /* Shift JIS character */
923             string_put_char(&str, *s++);
924             if (*s)
925                 string_put_char(&str, *s++);
926         }
927         else if (*s != '%')
928         {
929             /* normal ASCII character */
930             string_put_char(&str, *s++);
931         }
932         else
933         {
934             /* output with format */
935             enum
936             {
937                 flag_blank = 000001,   /* ' ' */
938                 flag_plus = 000002,    /* '+' */
939                 flag_sharp = 000004,   /* '#' */
940                 flag_minus = 000010,   /* '-' */
941                 flag_zero = 000020,    /* '0' */
942                 flag_l1 = 000040,      /* "l" */
943                 flag_h1 = 000100,      /* "h" */
944                 flag_l2 = 000200,      /* "ll" */
945                 flag_h2 = 000400,      /* "hh" */
946                 flag_unsigned = 010000, /* 'o', 'u', ... */
947                 flag_binary = 020000,  /* 'b' */
948                 flag_colon = 040000,   /* ':' */
949                 flag_end
950             };
951             int     flag = 0, width = 0, precision = -1, radix = 10;
952             char    hex_char = 'a' - 10;
953             const char *p_start = s;
954             /* flags */
955             for (;;)
956             {
957                 switch (*++s)
958                 {
959                 case '+':
960                     if (s[-1] != ' ')
961                         break;
962                     flag |= flag_plus;
963                     continue;
964                 case ' ':
965                     flag |= flag_blank;
966                     continue;
967                 case '-':
968                     flag |= flag_minus;
969                     continue;
970                 case '0':
971                     flag |= flag_zero;
972                     continue;
973                 case ':':
974                     flag |= flag_colon;
975                     continue;
976                 }
977                 break;
978             }
979             /* Width */
980             if (*s == '*')
981             {
982                 ++s, width = va_arg(vlist, int);
983                 if (width < 0)
984                     width = -width, flag |= flag_minus;
985             }
986             else
987             {
988                 while ((*s >= '0') && (*s <= '9'))
989                     width = (width * 10) + *s++ - '0';
990             }
991             /* precision */
992             if (*s == '.')
993             {
994                 ++s, precision = 0;
995                 if (*s == '*')
996                 {
997                     ++s, precision = va_arg(vlist, int);
998                     if (precision < 0)
999                         precision = -1;
1000                 }
1001                 else
1002                 {
1003                     while ((*s >= '0') && (*s <= '9'))
1004                         precision = (precision * 10) + *s++ - '0';
1005                 }
1006             }
1007             /* Options */
1008             switch (*s)
1009             {
1010             case 'h':
1011                 if (*++s != 'h')
1012                     flag |= flag_h1;
1013                 else
1014                     ++s, flag |= flag_h2;
1015                 break;
1016             case 'l':
1017                 if (*++s != 'l')
1018                     flag |= flag_l1;
1019                 else
1020                     ++s, flag |= flag_l2;
1021                 break;
1022             }
1023 
1024             /* type */
1025             switch (*s)
1026             {
1027             case 'd':                 /* signed decimal */
1028             case 'i':                 /* signed decimal */
1029                 goto put_integer;
1030             case 'o':                 /* unsigned octal */
1031                 radix = 8;
1032                 flag |= flag_unsigned;
1033                 goto put_integer;
1034             case 'u':                 /* unsigned decimal */
1035                 flag |= flag_unsigned;
1036                 goto put_integer;
1037             case 'X':                 /* unsigned hexadecimal */
1038                 hex_char = 'A' - 10;
1039                 goto put_hexadecimal;
1040             case 'x':                 /* unsigned hexadecimal */
1041                 goto put_hexadecimal;
1042             case 'p':                 /* pointer */
1043                 /* equal to code warrior */
1044                 flag |= flag_sharp;
1045                 precision = 8;
1046                 goto put_hexadecimal;
1047 
1048             case 'C':                 /* unicode-character */
1049                 flag |= flag_l1;
1050             case 'c':                 /* character */
1051                 if (precision >= 0)
1052                     goto put_invalid;
1053                 {
1054                     int     c = va_arg(vlist, int);
1055                     width -= 1;
1056                     if (flag & flag_minus)
1057                     {
1058                         if (flag & flag_l1)
1059                         {
1060                             char    dst[2];
1061 
1062                             if (STD_ConvertCharUnicodeToSjis(dst, (u16)c) == 1)
1063                             {
1064                                 string_put_char(&str, dst[0]);
1065                             }
1066                             else
1067                             {
1068                                 string_put_string(&str, dst, 2);
1069                             }
1070                         }
1071                         else
1072                         {
1073                             string_put_char(&str, (char)c);
1074                         }
1075                         string_fill_char(&str, ' ', width);
1076                     }
1077                     else
1078                     {
1079                         char    pad = (char)((flag & flag_zero) ? '0' : ' ');
1080                         string_fill_char(&str, pad, width);
1081 
1082                         if (flag & flag_l1)
1083                         {
1084                             char    dst[2];
1085 
1086                             if (STD_ConvertCharUnicodeToSjis(dst, (u16)c) == 1)
1087                             {
1088                                 string_put_char(&str, dst[0]);
1089                             }
1090                             else
1091                             {
1092                                 string_put_string(&str, dst, 2);
1093                             }
1094                         }
1095                         else
1096                         {
1097                             string_put_char(&str, (char)c);
1098                         }
1099                     }
1100                     ++s;
1101                 }
1102                 break;
1103 
1104             case 'S':                 /* unicode-string */
1105                 flag |= flag_l1;
1106             case 's':                 /* string */
1107                 {
1108                     int     n_buf = 0;
1109                     const char *p_buf = va_arg(vlist, const char *);
1110 
1111                     if (precision < 0)
1112                     {
1113                         while (p_buf[n_buf])
1114                         {
1115                             if (flag & flag_l1)
1116                             {
1117                                 n_buf += 2;
1118                             }
1119                             else
1120                             {
1121                                 ++n_buf;
1122                             }
1123                         }
1124                     }
1125                     else
1126                     {
1127                         while ((n_buf < precision) && p_buf[n_buf])
1128                         {
1129                             if (flag & flag_l1)
1130                             {
1131                                 n_buf += 2;
1132                             }
1133                             else
1134                             {
1135                                 ++n_buf;
1136                             }
1137                         }
1138                     }
1139                     if (flag & flag_l1)
1140                     {
1141                         n_buf /= 2;
1142                     }
1143                     width -= n_buf;
1144                     if (flag & flag_minus)
1145                     {
1146                         if (flag & flag_l1)
1147                         {
1148                             u16    *w_buf = (u16 *)p_buf;
1149                             char    dst[2];
1150 
1151                             while (n_buf--)
1152                             {
1153                                 if (STD_ConvertCharUnicodeToSjis(dst, *w_buf) == 1)
1154                                 {
1155                                     string_put_char(&str, dst[0]);
1156                                 }
1157                                 else
1158                                 {
1159                                     string_put_string(&str, dst, 2);
1160                                 }
1161                                 w_buf++;
1162                             }
1163                         }
1164                         else
1165                         {
1166                             string_put_string(&str, p_buf, n_buf);
1167                         }
1168                         string_fill_char(&str, ' ', width);
1169                     }
1170                     else
1171                     {
1172                         char    pad = (char)((flag & flag_zero) ? '0' : ' ');
1173                         string_fill_char(&str, pad, width);
1174 
1175                         if (flag & flag_l1)
1176                         {
1177                             u16    *w_buf = (u16 *)p_buf;
1178                             char    dst[2];
1179 
1180                             while (n_buf--)
1181                             {
1182                                 if (STD_ConvertCharUnicodeToSjis(dst, *w_buf) == 1)
1183                                 {
1184                                     string_put_char(&str, dst[0]);
1185                                 }
1186                                 else
1187                                 {
1188                                     string_put_string(&str, dst, 2);
1189                                 }
1190                                 w_buf++;
1191                             }
1192                         }
1193                         else
1194                         {
1195                             string_put_string(&str, p_buf, n_buf);
1196                         }
1197                     }
1198                     ++s;
1199                 }
1200                 break;
1201 
1202             case 'B':                 /* binary */
1203                 hex_char = 'A' - 10;
1204             case 'b':                 /* binary */
1205                 {
1206                     int     n_buf = width;
1207                     int     count = 0;
1208                     char   *p_buf = va_arg(vlist, char *);
1209                     int     column_count;
1210 
1211                     if (n_buf <= 0)
1212                     {
1213                         n_buf = 1;
1214                     }
1215                     if (precision == 0)
1216                     {
1217                         precision = -1;
1218                     }
1219                     column_count = precision;
1220 
1221                     while (1)
1222                     {
1223                         char    left_char, right_char;
1224                         int     left = ((p_buf[count] & 0xF0) >> 4);
1225                         int     right = (p_buf[count] & 0x0F);
1226 
1227                         left_char = (char)((left < 10) ? (left + '0') : (left + hex_char));
1228                         right_char = (char)((right < 10) ? (right + '0') : (right + hex_char));
1229 
1230                         string_put_char(&str, left_char);
1231                         string_put_char(&str, right_char);
1232 
1233                         count++;
1234 
1235                         if (count >= n_buf)
1236                             break;
1237 
1238                         if (column_count > 0)
1239                         {
1240                             --column_count;
1241                         }
1242 
1243                         if (column_count == 0)
1244                         {
1245                             string_put_char(&str, '\n');
1246                             if ((flag & flag_blank) && !(flag & flag_minus))
1247                             {
1248                                 string_put_char(&str, ' ');
1249                             }
1250                             column_count = precision;
1251                         }
1252                         else if (flag & flag_colon)
1253                         {
1254                             string_put_char(&str, ':');
1255                         }
1256                         else if (flag & flag_blank)
1257                         {
1258                             string_put_char(&str, ' ');
1259                         }
1260                     }
1261                     ++s;
1262                 }
1263                 break;
1264 
1265             case 'n':                 /* store the number of output */
1266                 {
1267                     int     pos = str.cur - str.base;
1268                     if (flag & flag_h2)
1269                         ;
1270                     else if (flag & flag_h1)
1271                         *va_arg(vlist, signed short *) = (signed short)pos;
1272                     else if (flag & flag_l2)
1273                         *va_arg(vlist, u64 *) = (u64)pos;
1274                     else
1275                         *va_arg(vlist, signed int *) = (signed int)pos;
1276                 }
1277                 ++s;
1278                 break;
1279 
1280             case '%':                 /* output '%' */
1281                 if (p_start + 1 != s)
1282                     goto put_invalid;
1283                 string_put_char(&str, *s++);
1284                 break;
1285 
1286             default:                  /* invalid type */
1287                 goto put_invalid;
1288 
1289               put_invalid:
1290                 string_put_string(&str, p_start, s - p_start);
1291                 break;
1292 
1293               put_hexadecimal:
1294                 radix = 16;
1295                 flag |= flag_unsigned;
1296               put_integer:
1297                 {
1298                     u64     val = 0;
1299                     n_prefix = 0;
1300 
1301                     if (flag & flag_minus)
1302                         flag &= ~flag_zero;
1303                     if (precision < 0)
1304                         precision = 1;
1305                     else
1306                         flag &= ~flag_zero;
1307 
1308                     if (flag & flag_unsigned)
1309                     {
1310                         if (flag & flag_h2)
1311                             val = va_arg(vlist, unsigned char);
1312                         else if (flag & flag_h1)
1313                             val = va_arg(vlist, unsigned short);
1314                         else if (flag & flag_l2)
1315                             val = va_arg(vlist, u64);
1316                         else
1317                             val = va_arg(vlist, unsigned long);
1318                         flag &= ~(flag_plus | flag_blank);
1319                         if (flag & flag_sharp)
1320                         {
1321                             if (radix == 16)
1322                             {
1323                                 if (val != 0)
1324                                 {
1325                                     prefix[0] = (char)(hex_char + (10 + 'x' - 'a'));
1326                                     prefix[1] = '0';
1327                                     n_prefix = 2;
1328                                 }
1329                             }
1330                             else if (radix == 8)
1331                             {
1332                                 prefix[0] = '0';
1333                                 n_prefix = 1;
1334                             }
1335                         }
1336                     }
1337                     else
1338                     {
1339                         if (flag & flag_h2)
1340                             val = va_arg(vlist, char);
1341                         else if (flag & flag_h1)
1342                             val = va_arg(vlist, short);
1343                         else if (flag & flag_l2)
1344                             val = va_arg(vlist, u64);
1345                         else
1346                             val = va_arg(vlist, long);
1347                         if ((val >> 32) & 0x80000000)
1348                         {
1349                             val = ~val + 1;
1350                             prefix[0] = '-';
1351                             n_prefix = 1;
1352                         }
1353                         else
1354                         {
1355                             if (val || precision)
1356                             {
1357                                 if (flag & flag_plus)
1358                                 {
1359                                     prefix[0] = '+';
1360                                     n_prefix = 1;
1361                                 }
1362                                 else if (flag & flag_blank)
1363                                 {
1364                                     prefix[0] = ' ';
1365                                     n_prefix = 1;
1366                                 }
1367                             }
1368                         }
1369                     }
1370                     n_buf = 0;
1371                     switch (radix)
1372                     {
1373                     case 8:
1374                         while (val != 0)
1375                         {
1376                             int     d = (int)(val & 0x07);
1377                             val >>= 3;
1378                             buf[n_buf++] = (char)(d + '0');
1379                         }
1380                         break;
1381                     case 10:
1382                         if ((val >> 32) == 0)
1383                         {
1384 #if defined(SDK_CW) || defined(SDK_RX) || defined(__MWERKS__)
1385 #pragma optimize_for_size off
1386 #endif
1387                             u32     v = (u32)val;
1388                             while (v != 0)
1389                             {
1390                                 // If the operation is division of a u32 and a constant, the compiler automatically converts it to addition using magic numbers
1391                                 //
1392                                 u32     r = v / 10;
1393                                 int     d = (int)(v - (r * 10));
1394                                 v = r;
1395                                 buf[n_buf++] = (char)(d + '0');
1396                             }
1397                         }
1398                         else
1399                         {
1400                             while (val != 0)
1401                             {
1402                                 u64     r = val / 10;
1403                                 int     d = (int)(val - (r * 10));
1404                                 val = r;
1405                                 buf[n_buf++] = (char)(d + '0');
1406                             }
1407                         }
1408                         break;
1409                     case 16:
1410                         while (val != 0)
1411                         {
1412                             int     d = (int)(val & 0x0f);
1413                             val >>= 4;
1414                             buf[n_buf++] = (char)((d < 10) ? (d + '0') : (d + hex_char));
1415                         }
1416                         break;
1417                     }
1418                     if ((n_prefix > 0) && (prefix[0] == '0'))
1419                     {
1420                         n_prefix = 0;
1421                         buf[n_buf++] = '0';
1422                     }
1423                 }
1424                 goto put_to_stream;
1425 
1426               put_to_stream:
1427                 {
1428                     int     n_pad = precision - n_buf;
1429                     if (flag & flag_zero)
1430                     {
1431                         if (n_pad < width - n_buf - n_prefix)
1432                             n_pad = width - n_buf - n_prefix;
1433                     }
1434                     if (n_pad > 0)
1435                         width -= n_pad;
1436                     width -= n_prefix + n_buf;
1437                     if (!(flag & flag_minus))
1438                         string_fill_char(&str, ' ', width);
1439                     while (n_prefix > 0)
1440                         string_put_char(&str, prefix[--n_prefix]);
1441                     string_fill_char(&str, '0', n_pad);
1442                     while (n_buf > 0)
1443                         string_put_char(&str, buf[--n_buf]);
1444                     if (flag & flag_minus)
1445                         string_fill_char(&str, ' ', width);
1446                     ++s;
1447                 }
1448                 break;
1449             }
1450         }
1451     }
1452 
1453     if (str.len > 0)
1454         *str.cur = '\0';
1455     else if (len > 0)
1456         str.base[len - 1] = '\0';
1457     return str.cur - str.base;
1458 }
1459 
1460 
1461 #if defined(SDK_CW_WARNOFF_SAFESTRB)
1462 #include <nitro/codereset.h>
1463 #endif
1464 
1465 //================================================================================
1466 //              Set output of print (for IS-TWL-DEBUGGER)
1467 //================================================================================
1468 #ifndef SDK_FINALROM
1469 #ifdef  SDK_LINK_ISTD
1470 /*---------------------------------------------------------------------------*
1471   Name:         OS_SetPrintOutput
1472 
1473   Description:  Specifies the output window OS_Printf uses.
1474                 This is only for IS-TWL-DEBUGGER.
1475 
1476   Arguments:    proc : processor
1477                          OS_PRINT_OUTPUT_PROC_ARM9     : ARM9
1478                          OS_PRINT_OUTPUT_PROC_ARM7     : ARM7
1479                          OS_PRINT_OUTPUT_PROC_ARM9ERR  : ARM9 for error
1480                          OS_PRINT_OUTPUT_PROC_ARM7ERR  : ARM7 for error
1481                 num: Window number (0-3)
1482 
1483   Returns:      None.
1484  *---------------------------------------------------------------------------*/
OS_SetPrintOutput(OSPrintOutputProc proc,int num)1485 void OS_SetPrintOutput( OSPrintOutputProc proc, int num )
1486 {
1487     SDK_ASSERT( (0<=num && num<=OS_PRINT_OUTPUT_WINDOW_MAX) || num==OS_PRINT_OUTPUT_NONE );
1488     SDK_ASSERT( 0<=(int)proc && (int)proc<=OS_PRINT_OUTPUT_PROC_ARM7ERR );
1489 	*(u8*)(HW_PRINT_OUTPUT_ARM9 + proc) = (u8)num;
1490 }
1491 #endif
1492 #endif
1493 
1494 //================================================================================
1495 //              FPutString hook
1496 //================================================================================
1497 #ifndef SDK_FINALROM
1498 /*---------------------------------------------------------------------------*
1499   Name:         OS_SetFPutStringHook
1500 
1501   Description:  Sets hook function in FPutString.
1502 
1503   Arguments:    func : hook function
1504 
1505   Returns:      None.
1506  *---------------------------------------------------------------------------*/
OS_SetFPutStringHook(OSFPutStringHookType func)1507 void OS_SetFPutStringHook( OSFPutStringHookType func )
1508 {
1509 	OSi_FPutStringHook = func;
1510 }
1511 
1512 /*---------------------------------------------------------------------------*
1513   Name:         OS_GetFPutStringHook
1514 
1515   Description:  get hook function in FPutString
1516 
1517   Arguments:    None.
1518 
1519   Returns:      hook function
1520  *---------------------------------------------------------------------------*/
OS_GetFPutStringHook(void)1521 OSFPutStringHookType OS_GetFPutStringHook(void)
1522 {
1523 	return OSi_FPutStringHook;
1524 }
1525 #endif
1526 
1527 //================================================================================
1528 //              DUMMY PRINT (stub for FINALROM)
1529 //================================================================================
1530 #ifdef SDK_FINALROM
1531 #ifdef OS_Printf
1532 #undef OS_Printf
1533 #endif
1534 void    OS_Printf(const char *fmt, ...);
OS_Printf(const char * fmt,...)1535 void OS_Printf(const char *fmt, ...)
1536 {
1537 #pragma unused( fmt )
1538 }
1539 #endif
1540 
1541 //================================================================================
1542 //              Blocking mode
1543 //================================================================================
1544 /*---------------------------------------------------------------------------*
1545   Name:         OS_SetPrintBlocking
1546 
1547   Description:  set blocking mode on debug print
1548 
1549   Arguments:    sw : blocking mode to set.
1550                      TRUE if want to block mode, or FALSE if not.
1551 
1552   Returns:      None
1553  *---------------------------------------------------------------------------*/
1554 #ifndef SDK_FINALROM
1555 void ISTDPrintSetBlockingMode(BOOL);
1556 void ISDPrintSetBlockingMode(int);
1557 
OS_SetPrintBlockingMode(BOOL sw)1558 void OS_SetPrintBlockingMode( BOOL sw )
1559 {
1560     if ( OS_IsRunOnTwl() )
1561     {
1562         ISTDPrintSetBlockingMode( sw );
1563     }
1564     else
1565     {
1566         ISDPrintSetBlockingMode( (int)sw );
1567     }
1568 }
1569 #endif // ifndef SDK_FINALROM
1570 
1571 /*---------------------------------------------------------------------------*
1572   Name:         OS_GetPrintBlockingMode
1573 
1574   Description:  get blocking mode on debug print
1575 
1576   Arguments:    None.
1577 
1578   Returns:      blocking mode.
1579                 TRUE if blocking is available, FALSE if not.
1580  *---------------------------------------------------------------------------*/
1581 #ifndef SDK_FINALROM
1582 BOOL ISTDPrintGetBlockingMode(void);
1583 int  ISDPrintGetBlockingMode(void);
1584 
OS_GetPrintBlockingMode(void)1585 BOOL OS_GetPrintBlockingMode( void )
1586 {
1587     if ( OS_IsRunOnTwl() )
1588     {
1589         return ISTDPrintGetBlockingMode()? TRUE: FALSE;
1590     }
1591     else
1592     {
1593         return ISDPrintGetBlockingMode()? TRUE: FALSE;
1594     }
1595 }
1596 #endif // ifndef SDK_FINALROM
1597