mirror of
https://github.com/rvtr/twl_wrapsdk.git
synced 2025-06-18 14:25:43 -04:00
1212 lines
36 KiB
C
1212 lines
36 KiB
C
/*---------------------------------------------------------------------------*
|
|
Project: NitroSDK - libraries - OS
|
|
File: os_printf.c
|
|
|
|
Copyright 2003-2006 Nintendo. All rights reserved.
|
|
|
|
These coded instructions, statements, and computer programs contain
|
|
proprietary information of Nintendo of America Inc. and/or Nintendo
|
|
Company Ltd., and are protected by Federal copyright law. They may
|
|
not be disclosed to third parties or copied or duplicated in any form,
|
|
in whole or in part, without the prior written consent of Nintendo.
|
|
|
|
$Log: os_printf.c,v $
|
|
Revision 1.48 2006/01/18 02:11:30 kitase_hirotake
|
|
do-indent
|
|
|
|
Revision 1.47 2005/10/12 08:32:38 yada
|
|
OS_PutString() is deadstripped in case of SDK_FINALROM
|
|
|
|
Revision 1.46 2005/06/23 12:08:37 yasu
|
|
SDK_LITTLE_ENDIAN を使用しないように修正
|
|
|
|
Revision 1.45 2005/06/07 09:49:34 yasu
|
|
UnitTest 対策のため OSi_Panic の OS_Terminate 呼び出しを変更可能にする
|
|
|
|
Revision 1.44 2005/03/04 11:09:27 yasu
|
|
__declspec(weak) を SDK_WEAK_SYMBOL に置き換え
|
|
|
|
Revision 1.43 2005/02/28 05:26:29 yosizaki
|
|
do-indent.
|
|
|
|
Revision 1.42 2005/02/28 04:26:25 yosizaki
|
|
SDK_NO_MESSAGE に関する小さな修正.
|
|
|
|
Revision 1.41 2005/02/18 06:22:52 yasu
|
|
Signed/Unsigned 変換警告抑制
|
|
|
|
Revision 1.40 2005/02/04 11:02:15 yasu
|
|
著作年の修正
|
|
|
|
Revision 1.39 2005/01/31 03:16:15 seiki_masashi
|
|
除算の除去のため、常に速度優先で最適化を行うように指定
|
|
|
|
Revision 1.38 2005/01/28 12:58:25 seiki_masashi
|
|
OS_VSNPrintf で除算をできるだけ使わないように変更
|
|
|
|
Revision 1.37 2004/11/24 11:07:37 yada
|
|
Let a few functions be weak symbol.
|
|
|
|
Revision 1.36 2004/11/24 08:50:22 yada
|
|
Let a few functions be weak symbol.
|
|
|
|
Revision 1.35 2004/11/12 10:45:30 yada
|
|
just fix comment
|
|
|
|
Revision 1.34 2004/10/08 07:49:13 yada
|
|
consider for the situation of not calling OS_InitPrintServer()
|
|
|
|
Revision 1.33 2004/10/04 10:06:30 yasu
|
|
support SDK_NO_MESSAGE
|
|
|
|
Revision 1.32 2004/09/11 06:00:34 yasu
|
|
Add OS_TPrintf
|
|
|
|
Revision 1.31 2004/06/08 01:22:47 yada
|
|
add stub OS_Printf() for FINALROM
|
|
|
|
Revision 1.30 2004/06/08 00:31:31 yada
|
|
invalidate debug functions(OS_Printf, etc.) when FINALROM
|
|
|
|
Revision 1.29 2004/05/06 02:54:39 yada
|
|
stop by OS_Terminate() in OSi_Panic(), not by OS_Halt()
|
|
|
|
Revision 1.28 2004/04/08 02:47:05 takano_makoto
|
|
Change to use OS_VSNPrintf() in ARM7.
|
|
|
|
Revision 1.27 2004/03/26 06:52:15 yosizaki
|
|
add OS_SPrintf, OS_VSPrintf, OS_SNPrintf, and OS_VSNPrintf.
|
|
|
|
Revision 1.26 2004/03/05 09:41:48 yasu
|
|
add SDK_NO_VSNPRINTF to disable vsnprintf
|
|
|
|
Revision 1.25 2004/03/04 12:41:05 yasu
|
|
change function typedef name
|
|
|
|
Revision 1.24 2004/02/28 12:07:55 yasu
|
|
fix buffer handling
|
|
|
|
Revision 1.23 2004/02/28 09:47:10 yasu
|
|
fix comment
|
|
|
|
Revision 1.22 2004/02/18 01:09:26 yasu
|
|
force to turn byte access warning off
|
|
|
|
Revision 1.21 2004/02/16 11:43:42 yasu
|
|
fix OS_PrintServer
|
|
|
|
Revision 1.20 2004/02/14 09:40:59 yasu
|
|
workaround for unused warning message
|
|
|
|
Revision 1.19 2004/02/14 09:26:08 yasu
|
|
move printserver into os_printf
|
|
|
|
Revision 1.18 2004/02/14 07:07:24 yasu
|
|
support printserver component
|
|
|
|
Revision 1.17 2004/02/13 08:58:52 yasu
|
|
nitro_sp.h -> nitro.h
|
|
|
|
Revision 1.16 2004/02/13 01:50:10 yada
|
|
ARM9とAMR7 でインクルードファイル場合わけ
|
|
|
|
Revision 1.15 2004/02/05 08:38:44 yada
|
|
only modify comment
|
|
|
|
Revision 1.14 2004/02/05 07:09:02 yasu
|
|
change SDK prefix iris -> nitro
|
|
|
|
Revision 1.13 2004/01/26 09:05:05 yasu
|
|
Link stub of ISDPrintf if no IS_IRIS_DIR
|
|
|
|
Revision 1.12 2003/12/29 04:27:24 yasu
|
|
workaround for OS_Warning, OS_Panic
|
|
|
|
Revision 1.11 2003/12/25 07:31:26 yada
|
|
型ルール統一による変更
|
|
|
|
Revision 1.10 2003/12/17 08:21:56 yasu
|
|
ARM7 との共用コード化
|
|
|
|
Revision 1.9 2003/12/16 10:46:16 yasu
|
|
ARM9/7 共用コード化
|
|
|
|
Revision 1.8 2003/12/12 05:03:48 yasu
|
|
vsprintf の strb 対応版がリリースされるまでのワークアラウンド追加
|
|
|
|
Revision 1.7 2003/12/10 12:20:50 yasu
|
|
IS ライブラリに関する小修正
|
|
|
|
Revision 1.6 2003/12/10 10:57:08 yasu
|
|
ISDPrint の組み込み
|
|
TEG ボードへの出力可能になる
|
|
|
|
Revision 1.5 2003/12/02 07:28:59 yasu
|
|
warning の回避
|
|
|
|
Revision 1.4 2003/12/02 06:51:51 yasu
|
|
空行変更
|
|
|
|
Revision 1.3 2003/12/02 03:44:50 yasu
|
|
IS-IRIS-EMULATOR 用ライブラリ向けの修正2
|
|
|
|
Revision 1.2 2003/12/02 02:38:49 yasu
|
|
ISDebugger での printout の組み込みの初段階
|
|
|
|
Revision 1.1 2003/11/29 01:25:46 yada
|
|
ファイル名称変更
|
|
|
|
Revision 1.8 2003/11/25 11:17:37 yasu
|
|
エミュレータの自動判別追加
|
|
|
|
Revision 1.7 2003/11/25 00:03:44 yasu
|
|
OS_PutChar/OS_PutString/OS_VPrintf の公開
|
|
|
|
Revision 1.6 2003/11/21 12:20:31 yada
|
|
reg_EMU_CONSOLE_OUT を reg_OS_EMU_CONSOLE_OUT にした。
|
|
|
|
Revision 1.5 2003/11/14 08:07:46 yasu
|
|
string buffer をスタックから取るのを止めて static にする
|
|
|
|
Revision 1.4 2003/11/14 07:46:00 yasu
|
|
微修正
|
|
|
|
Revision 1.3 2003/11/14 06:14:03 yasu
|
|
OS_Warning() OS_Panic() の追加
|
|
|
|
Revision 1.2 2003/11/13 11:59:01 yasu
|
|
初版作成
|
|
|
|
Revision 1.1 2003/11/13 11:24:08 yasu
|
|
初版作成 エミュレータ側の実装が終わっていないため動作しないと思われる
|
|
|
|
$NoKeywords: $
|
|
*---------------------------------------------------------------------------*/
|
|
#include <nitro.h>
|
|
#include <twl/vlink.h>
|
|
|
|
#ifdef SDK_LINK_ISD
|
|
# pragma warn_extracomma off
|
|
# include <isdbglib.h> // has extracomma in enum
|
|
# pragma warn_extracomma reset
|
|
#else
|
|
void ISDPrint(const char *);
|
|
#endif
|
|
|
|
#ifndef SDK_FINALROM
|
|
static char common_buffer[256]; // thread unsafe, but less use of stack
|
|
#endif
|
|
|
|
#if !defined(SDK_FINALROM) && defined(SDK_NO_MESSAGE)
|
|
#undef OSi_Warning
|
|
#undef OSi_TWarning
|
|
#undef OSi_Panic
|
|
#undef OSi_TPanic
|
|
void OSi_Warning(const char *file, int line, const char *fmt, ...);
|
|
void OSi_TWarning(const char *file, int line, const char *fmt, ...);
|
|
void OSi_Panic(const char *file, int line, const char *fmt, ...);
|
|
void OSi_TPanic(const char *file, int line, const char *fmt, ...);
|
|
#endif /* SDK_NO_MESSAGE */
|
|
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_PutChar
|
|
|
|
Description: put a letter for debug console
|
|
|
|
Arguments: c : char code , shuild be 0x01-0xff
|
|
|
|
Returns: None.
|
|
*---------------------------------------------------------------------------*/
|
|
#ifndef SDK_FINALROM
|
|
SDK_WEAK_SYMBOL void OS_PutChar(char c)
|
|
{
|
|
char str[2];
|
|
|
|
str[0] = c;
|
|
str[1] = '\0';
|
|
|
|
// Because of no putchar-type function on ISDebugger library,
|
|
// use 'putstring' for a single letter outputting
|
|
OS_PutString(str);
|
|
}
|
|
#endif
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_PutString
|
|
|
|
Description: put a string to debug console.
|
|
console port are automatically switched depends on emu/hw
|
|
|
|
Arguments: str : string
|
|
|
|
Returns: None.
|
|
*---------------------------------------------------------------------------*/
|
|
static void OS_PutStringInit(const char *str);
|
|
|
|
#ifndef SDK_FINALROM
|
|
static void OS_PutStringAris(const char *str);
|
|
static void OS_PutStringISD(const char *str);
|
|
static void OS_PutStringKMC(const char *str);
|
|
void OS_PutStringARM(const char *str);
|
|
#ifdef SDK_ARM7
|
|
static void OS_PutStringPrnSrv(const char *str);
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef SDK_FINALROM
|
|
void (*OS_PutString) (const char *str) = OS_PutStringInit;
|
|
#endif
|
|
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_PutStringInit
|
|
Description: OS_PutString initializer
|
|
*---------------------------------------------------------------------------*/
|
|
static void OS_PutStringInit(const char *str)
|
|
{
|
|
#ifndef SDK_FINALROM
|
|
OSIntrMode intr = OS_DisableInterrupts();
|
|
|
|
#ifdef SDK_ARM9
|
|
if (OS_IsRunOnEmulator())
|
|
{
|
|
OS_PutString = OS_PutStringAris;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
#ifdef SDK_ARM7
|
|
OS_PutString = OS_PutStringPrnSrv;
|
|
#else
|
|
OS_PutString = OS_PutStringKMC;
|
|
#endif
|
|
OS_PutString = OS_PutStringKMC;
|
|
#ifdef SDK_DEBUGGER_ARM
|
|
OS_PutString = OS_PutStringARM;
|
|
#endif
|
|
}
|
|
|
|
OS_PutString(str);
|
|
|
|
(void)OS_RestoreInterrupts(intr);
|
|
|
|
#else
|
|
(void)str; // avoiding to unused warning
|
|
#endif
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_PutStringAris
|
|
Description: OS_PutString for software simulator called ARIS
|
|
*---------------------------------------------------------------------------*/
|
|
#ifndef SDK_FINALROM
|
|
#ifdef SDK_CW_WARNOFF_SAFESTRB
|
|
#include <nitro/code32.h>
|
|
#endif
|
|
static void OS_PutStringAris(const char *str)
|
|
{
|
|
char c;
|
|
|
|
while ('\0' != (c = *str))
|
|
{
|
|
reg_OS_EMU_CONSOLE_OUT = (u8)c; // Console out
|
|
str++;
|
|
}
|
|
}
|
|
|
|
#ifdef SDK_CW_WARNOFF_SAFESTRB
|
|
#include <nitro/codereset.h>
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_PutStringISD
|
|
Description: OS_PutString for hardware emulator called IS Debugger
|
|
*---------------------------------------------------------------------------*/
|
|
#ifndef SDK_FINALROM
|
|
static void OS_PutStringISD(const char *str)
|
|
{
|
|
// ISDPrint の初期化処理
|
|
OS_InitLock();
|
|
|
|
OS_PutString = ISDPrint;
|
|
OS_PutString(str);
|
|
}
|
|
#endif
|
|
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_PutStringKMC
|
|
Description: OS_PutString for hardware emulator called KMC Debugger
|
|
*---------------------------------------------------------------------------*/
|
|
#ifndef SDK_FINALROM
|
|
static void OS_PutStringKMC(const char *str)
|
|
{
|
|
vlink_dos_putstring_console((char *)str, STD_GetStringLength(str));
|
|
}
|
|
#endif
|
|
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_PutStringARM
|
|
Description: OS_PutString for hardware emulator called ARM Debugger
|
|
*---------------------------------------------------------------------------*/
|
|
#ifndef SDK_FINALROM
|
|
#include <nitro/code32.h>
|
|
asm void OS_PutStringARM(const char *str)
|
|
{
|
|
mov r1, r0
|
|
mov r0, #0x04
|
|
swi 0x123456
|
|
bx lr
|
|
}
|
|
#include <nitro/codereset.h>
|
|
#endif
|
|
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_VPrintf/OS_TVPrintf
|
|
|
|
Description: print formatted strings (vprintf ver.)
|
|
|
|
Arguments: fmt : format string
|
|
vlist : parameters
|
|
|
|
Returns: None.
|
|
*---------------------------------------------------------------------------*/
|
|
// If you want to use "vsnprintf()" in ARM7, define SDK_USE_VSNPRINTF.
|
|
// "vsnprintf()" is able to print float format but the code size become hugely bigger.
|
|
// #define SDK_USE_VSNPRINTF
|
|
|
|
#ifndef SDK_FINALROM
|
|
#if defined(SDK_ARM9) || defined(SDK_USE_VSNPRINTF)
|
|
SDK_WEAK_SYMBOL void OS_VPrintf(const char *fmt, va_list vlist)
|
|
{
|
|
(void)vsnprintf(common_buffer, sizeof(common_buffer), fmt, vlist);
|
|
OS_PutString(common_buffer);
|
|
}
|
|
#else
|
|
SDK_WEAK_SYMBOL void OS_VPrintf(const char *fmt, va_list vlist)
|
|
{
|
|
OS_TVPrintf(fmt, vlist);
|
|
}
|
|
#endif
|
|
SDK_WEAK_SYMBOL void OS_TVPrintf(const char *fmt, va_list vlist)
|
|
{
|
|
(void)OS_VSNPrintf(common_buffer, sizeof(common_buffer), fmt, vlist);
|
|
OS_PutString(common_buffer);
|
|
}
|
|
#endif
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_Printf/OS_TPrintf
|
|
|
|
Description: print formatted strings.
|
|
|
|
Arguments: fmt : format string
|
|
... and parameters
|
|
|
|
Returns: None.
|
|
*---------------------------------------------------------------------------*/
|
|
#ifndef SDK_FINALROM
|
|
SDK_WEAK_SYMBOL void OS_Printf(const char *fmt, ...)
|
|
{
|
|
va_list vlist;
|
|
|
|
va_start(vlist, fmt);
|
|
OS_VPrintf(fmt, vlist);
|
|
va_end(vlist);
|
|
}
|
|
|
|
SDK_WEAK_SYMBOL void OS_TPrintf(const char *fmt, ...)
|
|
{
|
|
va_list vlist;
|
|
|
|
va_start(vlist, fmt);
|
|
OS_TVPrintf(fmt, vlist);
|
|
va_end(vlist);
|
|
}
|
|
#endif
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OSi_Warning / OSi_TWarning
|
|
|
|
Description: print warning message.
|
|
|
|
Arguments: file : filename of warning location
|
|
line : line number of warning location
|
|
fmt : format string
|
|
... and parameters
|
|
|
|
Returns: None.
|
|
*---------------------------------------------------------------------------*/
|
|
#ifndef SDK_FINALROM
|
|
SDK_WEAK_SYMBOL void OSi_Warning(const char *file, int line, const char *fmt, ...)
|
|
{
|
|
va_list vlist;
|
|
|
|
va_start(vlist, fmt);
|
|
OS_Printf("%s:%d Warning:", file, line);
|
|
OS_VPrintf(fmt, vlist);
|
|
OS_Printf("\n");
|
|
va_end(vlist);
|
|
}
|
|
|
|
|
|
SDK_WEAK_SYMBOL void OSi_TWarning(const char *file, int line, const char *fmt, ...)
|
|
{
|
|
va_list vlist;
|
|
|
|
va_start(vlist, fmt);
|
|
OS_TPrintf("%s:%d Warning:", file, line);
|
|
OS_TVPrintf(fmt, vlist);
|
|
OS_TPrintf("\n");
|
|
va_end(vlist);
|
|
}
|
|
#endif
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OSi_Panic/OSi_TPanic
|
|
|
|
Description: print panic message and halt cpu.
|
|
|
|
Arguments: file : filename of panic location
|
|
line : line number of panic location
|
|
fmt : format string
|
|
... and parameters
|
|
|
|
Returns: None.
|
|
*---------------------------------------------------------------------------*/
|
|
#ifndef SDK_FINALROM
|
|
void (*OSi_FuncTerminate) (void) = OS_Terminate;
|
|
|
|
SDK_WEAK_SYMBOL void OSi_Panic(const char *file, int line, const char *fmt, ...)
|
|
{
|
|
va_list vlist;
|
|
|
|
va_start(vlist, fmt);
|
|
(void)OS_DisableInterrupts();
|
|
OS_Printf("%s:%d Panic:", file, line);
|
|
OS_VPrintf(fmt, vlist);
|
|
OS_Printf("\n");
|
|
OSi_FuncTerminate(); // Never Returns
|
|
}
|
|
|
|
SDK_WEAK_SYMBOL void OSi_TPanic(const char *file, int line, const char *fmt, ...)
|
|
{
|
|
va_list vlist;
|
|
|
|
va_start(vlist, fmt);
|
|
(void)OS_DisableInterrupts();
|
|
OS_TPrintf("%s:%d Panic:", file, line);
|
|
OS_TVPrintf(fmt, vlist);
|
|
OS_TPrintf("\n");
|
|
OSi_FuncTerminate(); // Never Returns
|
|
}
|
|
#endif
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_InitPrintServer
|
|
|
|
Description: initialize print server
|
|
- this code should be called before OS_InitLock()
|
|
- OS_InitLock() are also called from OS_Init()
|
|
|
|
Arguments: None
|
|
|
|
Returns: None
|
|
*---------------------------------------------------------------------------*/
|
|
#ifdef SDK_ARM9
|
|
#ifndef SDK_FINALROM
|
|
void OS_InitPrintServer(void)
|
|
{
|
|
OSPrintServerBuffer *p;
|
|
|
|
// first, allocate buffer and register it.
|
|
OS_InitArena();
|
|
p = OS_AllocFromSharedArenaHi(sizeof(OSPrintServerBuffer), 4);
|
|
p->in = p->out = 0UL;
|
|
PXI_SetComponentParam((u32)p);
|
|
}
|
|
#endif //SDK_FINALROM
|
|
#endif //SDK_ARM9
|
|
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_PrintServer
|
|
|
|
Description: print a string comes from ARM7 via shared memory
|
|
|
|
Arguments: str string
|
|
|
|
Returns: None.
|
|
*---------------------------------------------------------------------------*/
|
|
#ifdef SDK_ARM9
|
|
#ifndef SDK_FINALROM
|
|
#include <nitro/code32.h> // to access 'common_buffer' via cache
|
|
void OS_PrintServer(void)
|
|
{
|
|
OSPrintServerBuffer *p;
|
|
register OSPrintWChar word;
|
|
|
|
u32 in, out;
|
|
int i;
|
|
|
|
p = (OSPrintServerBuffer *)PXI_GetComponentParam();
|
|
|
|
//---- If print buffer isn't set up, do nothing.
|
|
if (!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
out = p->out;
|
|
in = p->in;
|
|
|
|
while (in != out)
|
|
{
|
|
i = 0;
|
|
|
|
while (in != out && i < sizeof(common_buffer) - 3)
|
|
{
|
|
word.s = p->buffer[out].s;
|
|
if (word.c[0])
|
|
{
|
|
common_buffer[i++] = word.c[0]; // store via cache
|
|
|
|
if (word.c[1])
|
|
{
|
|
common_buffer[i++] = word.c[1]; // store via cache
|
|
}
|
|
}
|
|
out++;
|
|
if (out >= OS_PRINTSRV_WCHARSIZE)
|
|
out = 0;
|
|
}
|
|
common_buffer[i] = '\0'; // store via cache
|
|
OS_PutString(common_buffer);
|
|
}
|
|
|
|
// tell finished
|
|
p->out = out;
|
|
}
|
|
|
|
#include <nitro/codereset.h>
|
|
#endif //SDK_FINALROM
|
|
#endif //SDK_ARM9
|
|
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_PutStringPrnSrv
|
|
|
|
Description: sends string to ARM9 via shared memory
|
|
|
|
Arguments: str string to be sent
|
|
|
|
Returns: None
|
|
*---------------------------------------------------------------------------*/
|
|
#ifdef SDK_ARM7
|
|
static void OS_PutStringPrnSrv(const char *str)
|
|
{
|
|
#ifndef SDK_FINALROM
|
|
OSPrintServerBuffer *p;
|
|
register OSPrintWChar word;
|
|
|
|
u32 in, in_tmp, out;
|
|
u32 isOdd;
|
|
|
|
p = (OSPrintServerBuffer *)PXI_GetComponentParam();
|
|
in = p->in;
|
|
out = p->out;
|
|
isOdd = ((u32)str) & 1;
|
|
|
|
while (1)
|
|
{
|
|
in_tmp = in + 1;
|
|
if (in_tmp >= OS_PRINTSRV_WCHARSIZE)
|
|
in_tmp = 0;
|
|
if (out == in_tmp)
|
|
break; // Buffer full, then exit
|
|
|
|
if (isOdd)
|
|
{
|
|
p->buffer[in].s = word.s = (u16)((*(u16 *)(str - 1)) & 0xff00);
|
|
str++;
|
|
isOdd = 0UL;
|
|
if (!word.c[1])
|
|
break;
|
|
in = in_tmp;
|
|
}
|
|
else
|
|
{
|
|
p->buffer[in].s = word.s = *(u16 *)str;
|
|
str += 2;
|
|
if (!word.c[0])
|
|
break;
|
|
in = in_tmp;
|
|
if (!word.c[1])
|
|
break;
|
|
}
|
|
}
|
|
p->in = in;
|
|
#else //SDK_FINALROM
|
|
(void)str;
|
|
#endif //SDK_FINALROM
|
|
}
|
|
#endif //SDK_ARM7
|
|
|
|
|
|
#if defined(SDK_CW_WARNOFF_SAFESTRB)
|
|
#include <nitro/code32.h>
|
|
#endif
|
|
|
|
/* inner function for sized-buffer output */
|
|
typedef struct dst_string_tag
|
|
{
|
|
size_t len;
|
|
char *cur;
|
|
char *base;
|
|
}
|
|
dst_string;
|
|
|
|
static void string_put_char(dst_string * p, char c)
|
|
{
|
|
if (p->len > 0)
|
|
*p->cur = c, --p->len;
|
|
++p->cur;
|
|
}
|
|
|
|
static void string_fill_char(dst_string * p, char c, int n)
|
|
{
|
|
if (n > 0)
|
|
{
|
|
size_t i, k = p->len;
|
|
if (k > (size_t) n)
|
|
k = (size_t) n;
|
|
for (i = 0; i < k; ++i)
|
|
p->cur[i] = c;
|
|
p->len -= k;
|
|
p->cur += n;
|
|
}
|
|
}
|
|
|
|
static void string_put_string(dst_string * p, const char *s, int n)
|
|
{
|
|
if (n > 0)
|
|
{
|
|
size_t i, k = p->len;
|
|
if (k > (size_t) n)
|
|
k = (size_t) n;
|
|
for (i = 0; i < k; ++i)
|
|
p->cur[i] = s[i];
|
|
p->len -= k;
|
|
p->cur += n;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_SPrintf
|
|
|
|
Description: equal to 'OS_VSPrintf' except argument style.
|
|
|
|
Arguments: dst : destination buffer.
|
|
fmt : format string.
|
|
|
|
Returns: length of the generated string.
|
|
*---------------------------------------------------------------------------*/
|
|
SDK_WEAK_SYMBOL int OS_SPrintf(char *dst, const char *fmt, ...)
|
|
{
|
|
int ret;
|
|
va_list va;
|
|
va_start(va, fmt);
|
|
ret = OS_VSPrintf(dst, fmt, va);
|
|
va_end(va);
|
|
return ret;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_VSPrintf
|
|
|
|
Description: equal to 'OS_VSNPrintf' except buffer size argument.
|
|
|
|
Arguments: dst : destination buffer.
|
|
fmt : format string.
|
|
vlist : parameters.
|
|
|
|
Returns: length of the generated string.
|
|
*---------------------------------------------------------------------------*/
|
|
SDK_WEAK_SYMBOL int OS_VSPrintf(char *dst, const char *fmt, va_list vlist)
|
|
{
|
|
return OS_VSNPrintf(dst, 0x7FFFFFFF, fmt, vlist);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_SNPrintf
|
|
|
|
Description: equal to 'OS_VSNPrintf' except argument style.
|
|
|
|
Arguments: dst : destination buffer.
|
|
len : destination buffer size.
|
|
fmt : format string.
|
|
|
|
Returns: length of the generated string. (except '\0')
|
|
if(result < len),
|
|
put NUL in dst[result].
|
|
else if(len > 0),
|
|
put NUL in dst[len - 1].
|
|
else,
|
|
do nothing.
|
|
*---------------------------------------------------------------------------*/
|
|
SDK_WEAK_SYMBOL int OS_SNPrintf(char *dst, size_t len, const char *fmt, ...)
|
|
{
|
|
int ret;
|
|
va_list va;
|
|
va_start(va, fmt);
|
|
ret = OS_VSNPrintf(dst, len, fmt, va);
|
|
va_end(va);
|
|
return ret;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: OS_VSNPrintf
|
|
|
|
Description: small-size vsnprintf which is similar to 'vsnprintf'
|
|
without following supports.
|
|
* CodeWarrior Extensions (#s)
|
|
* MSL AltiVec Extensions (v, vh, vl, hv, lv, @)
|
|
* indexed argments (%m$, *m$)
|
|
* floating-point
|
|
* wchar_t
|
|
|
|
Note: '+' and '#' do not work, MSL's sprintf().
|
|
to keep same result, they are no implement.
|
|
{ // exsample
|
|
char buf[5];
|
|
sprintf(buf, "%-i\n", 45); // "45" (OK)
|
|
sprintf(buf, "%0i\n", 45); // "45" (OK)
|
|
sprintf(buf, "% i\n", 45); // " 45" (OK)
|
|
sprintf(buf, "%+i\n", 45); // "%+i" ("+45" expected)
|
|
sprintf(buf, "%#x\n", 45); // "%#x" ("0x2d" expected)
|
|
// but, this works correctly!
|
|
sprintf(buf, "% +i\n", 45); // "+45" (OK)
|
|
}
|
|
|
|
Arguments: dst : destination buffer.
|
|
len : destination buffer size.
|
|
fmt : format string.
|
|
vlist : parameters.
|
|
|
|
Returns: length of the generated string. (except '\0')
|
|
if(result < len),
|
|
put NUL in dst[result].
|
|
else if(len > 0),
|
|
put NUL in dst[len - 1].
|
|
else,
|
|
do nothing.
|
|
*---------------------------------------------------------------------------*/
|
|
SDK_WEAK_SYMBOL int OS_VSNPrintf(char *dst, size_t len, const char *fmt, va_list vlist)
|
|
{
|
|
char buf[24];
|
|
int n_buf;
|
|
char prefix[2];
|
|
int n_prefix;
|
|
|
|
const char *s = fmt;
|
|
|
|
dst_string str;
|
|
str.len = len, str.cur = str.base = dst;
|
|
|
|
while (*s)
|
|
{
|
|
if ((unsigned int)(((unsigned char)*s ^ 0x20) - 0xA1) < 0x3C)
|
|
{
|
|
/* Shift JIS character */
|
|
string_put_char(&str, *s++);
|
|
if (*s)
|
|
string_put_char(&str, *s++);
|
|
}
|
|
else if (*s != '%')
|
|
{
|
|
/* normal ASCII character */
|
|
string_put_char(&str, *s++);
|
|
}
|
|
else
|
|
{
|
|
/* output with format */
|
|
enum
|
|
{
|
|
flag_blank = 000001, /* ' ' */
|
|
flag_plus = 000002, /* '+' */
|
|
flag_sharp = 000004, /* '#' */
|
|
flag_minus = 000010, /* '-' */
|
|
flag_zero = 000020, /* '0' */
|
|
flag_l1 = 000040, /* "l" */
|
|
flag_h1 = 000100, /* "h" */
|
|
flag_l2 = 000200, /* "ll" */
|
|
flag_h2 = 000400, /* "hh" */
|
|
flag_unsigned = 010000, /* 'o', 'u', ... */
|
|
flag_end
|
|
};
|
|
int flag = 0, width = 0, precision = -1, radix = 10;
|
|
char hex_char = 'a' - 10;
|
|
const char *p_start = s;
|
|
/* flags */
|
|
for (;;)
|
|
{
|
|
switch (*++s)
|
|
{
|
|
case '+':
|
|
if (s[-1] != ' ')
|
|
break;
|
|
flag |= flag_plus;
|
|
continue;
|
|
case ' ':
|
|
flag |= flag_blank;
|
|
continue;
|
|
case '-':
|
|
flag |= flag_minus;
|
|
continue;
|
|
case '0':
|
|
flag |= flag_zero;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
/* width */
|
|
if (*s == '*')
|
|
{
|
|
++s, width = va_arg(vlist, int);
|
|
if (width < 0)
|
|
width = -width, flag |= flag_minus;
|
|
}
|
|
else
|
|
{
|
|
while ((*s >= '0') && (*s <= '9'))
|
|
width = (width * 10) + *s++ - '0';
|
|
}
|
|
/* precision */
|
|
if (*s == '.')
|
|
{
|
|
++s, precision = 0;
|
|
if (*s == '*')
|
|
{
|
|
++s, precision = va_arg(vlist, int);
|
|
if (precision < 0)
|
|
precision = -1;
|
|
}
|
|
else
|
|
{
|
|
while ((*s >= '0') && (*s <= '9'))
|
|
precision = (precision * 10) + *s++ - '0';
|
|
}
|
|
}
|
|
/* option */
|
|
switch (*s)
|
|
{
|
|
case 'h':
|
|
if (*++s != 'h')
|
|
flag |= flag_h1;
|
|
else
|
|
++s, flag |= flag_h2;
|
|
break;
|
|
case 'l':
|
|
if (*++s != 'l')
|
|
flag |= flag_l1;
|
|
else
|
|
++s, flag |= flag_l2;
|
|
break;
|
|
}
|
|
|
|
/* type */
|
|
switch (*s)
|
|
{
|
|
case 'd': /* signed decimal */
|
|
case 'i': /* signed decimal */
|
|
goto put_integer;
|
|
case 'o': /* unsigned octal */
|
|
radix = 8;
|
|
flag |= flag_unsigned;
|
|
goto put_integer;
|
|
case 'u': /* unsigned decimal */
|
|
flag |= flag_unsigned;
|
|
goto put_integer;
|
|
case 'X': /* unsigned hexadecimal */
|
|
hex_char = 'A' - 10;
|
|
goto put_hexadecimal;
|
|
case 'x': /* unsigned hexadecimal */
|
|
goto put_hexadecimal;
|
|
case 'p': /* pointer */
|
|
/* equal to code warrior */
|
|
flag |= flag_sharp;
|
|
precision = 8;
|
|
goto put_hexadecimal;
|
|
|
|
case 'c': /* character */
|
|
if (precision >= 0)
|
|
goto put_invalid;
|
|
{
|
|
int c = va_arg(vlist, int);
|
|
width -= 1;
|
|
if (flag & flag_minus)
|
|
{
|
|
string_put_char(&str, (char)c);
|
|
string_fill_char(&str, ' ', width);
|
|
}
|
|
else
|
|
{
|
|
char pad = (char)((flag & flag_zero) ? '0' : ' ');
|
|
string_fill_char(&str, pad, width);
|
|
string_put_char(&str, (char)c);
|
|
}
|
|
++s;
|
|
}
|
|
break;
|
|
|
|
case 's': /* string */
|
|
{
|
|
int n_buf = 0;
|
|
const char *p_buf = va_arg(vlist, const char *);
|
|
if (precision < 0)
|
|
{
|
|
while (p_buf[n_buf])
|
|
++n_buf;
|
|
}
|
|
else
|
|
{
|
|
while ((n_buf < precision) && p_buf[n_buf])
|
|
++n_buf;
|
|
}
|
|
width -= n_buf;
|
|
if (flag & flag_minus)
|
|
{
|
|
string_put_string(&str, p_buf, n_buf);
|
|
string_fill_char(&str, ' ', width);
|
|
}
|
|
else
|
|
{
|
|
char pad = (char)((flag & flag_zero) ? '0' : ' ');
|
|
string_fill_char(&str, pad, width);
|
|
string_put_string(&str, p_buf, n_buf);
|
|
}
|
|
++s;
|
|
}
|
|
break;
|
|
|
|
case 'n': /* store the number of output */
|
|
{
|
|
int pos = str.cur - str.base;
|
|
if (flag & flag_h2)
|
|
;
|
|
else if (flag & flag_h1)
|
|
*va_arg(vlist, signed short *) = (signed short)pos;
|
|
else if (flag & flag_l2)
|
|
*va_arg(vlist, u64 *) = (u64)pos;
|
|
else
|
|
*va_arg(vlist, signed int *) = (signed int)pos;
|
|
}
|
|
++s;
|
|
break;
|
|
|
|
case '%': /* output '%' */
|
|
if (p_start + 1 != s)
|
|
goto put_invalid;
|
|
string_put_char(&str, *s++);
|
|
break;
|
|
|
|
default: /* invalid type */
|
|
goto put_invalid;
|
|
|
|
put_invalid:
|
|
string_put_string(&str, p_start, s - p_start);
|
|
break;
|
|
|
|
put_hexadecimal:
|
|
radix = 16;
|
|
flag |= flag_unsigned;
|
|
put_integer:
|
|
{
|
|
u64 val = 0;
|
|
n_prefix = 0;
|
|
|
|
if (flag & flag_minus)
|
|
flag &= ~flag_zero;
|
|
if (precision < 0)
|
|
precision = 1;
|
|
else
|
|
flag &= ~flag_zero;
|
|
|
|
if (flag & flag_unsigned)
|
|
{
|
|
if (flag & flag_h2)
|
|
val = va_arg(vlist, unsigned char);
|
|
else if (flag & flag_h1)
|
|
val = va_arg(vlist, unsigned short);
|
|
else if (flag & flag_l2)
|
|
val = va_arg(vlist, u64);
|
|
else
|
|
val = va_arg(vlist, unsigned long);
|
|
flag &= ~(flag_plus | flag_blank);
|
|
if (flag & flag_sharp)
|
|
{
|
|
if (radix == 16)
|
|
{
|
|
if (val != 0)
|
|
{
|
|
prefix[0] = (char)(hex_char + (10 + 'x' - 'a'));
|
|
prefix[1] = '0';
|
|
n_prefix = 2;
|
|
}
|
|
}
|
|
else if (radix == 8)
|
|
{
|
|
prefix[0] = '0';
|
|
n_prefix = 1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (flag & flag_h2)
|
|
val = va_arg(vlist, char);
|
|
else if (flag & flag_h1)
|
|
val = va_arg(vlist, short);
|
|
else if (flag & flag_l2)
|
|
val = va_arg(vlist, u64);
|
|
else
|
|
val = va_arg(vlist, long);
|
|
if ((val >> 32) & 0x80000000)
|
|
{
|
|
val = ~val + 1;
|
|
prefix[0] = '-';
|
|
n_prefix = 1;
|
|
}
|
|
else
|
|
{
|
|
if (val || precision)
|
|
{
|
|
if (flag & flag_plus)
|
|
{
|
|
prefix[0] = '+';
|
|
n_prefix = 1;
|
|
}
|
|
else if (flag & flag_blank)
|
|
{
|
|
prefix[0] = ' ';
|
|
n_prefix = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
n_buf = 0;
|
|
switch (radix)
|
|
{
|
|
case 8:
|
|
while (val != 0)
|
|
{
|
|
int d = (int)(val & 0x07);
|
|
val >>= 3;
|
|
buf[n_buf++] = (char)(d + '0');
|
|
}
|
|
break;
|
|
case 10:
|
|
if ((val >> 32) == 0)
|
|
{
|
|
#if defined(SDK_CW) || defined(__MWERKS__)
|
|
#pragma optimize_for_size off
|
|
#endif
|
|
u32 v = (u32)val;
|
|
while (v != 0)
|
|
{
|
|
// u32 と定数の除算であれば、コンパイラが自動的に
|
|
// マジックナンバーを使用した積算に変換する
|
|
u32 r = v / 10;
|
|
int d = (int)(v - (r * 10));
|
|
v = r;
|
|
buf[n_buf++] = (char)(d + '0');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (val != 0)
|
|
{
|
|
u64 r = val / 10;
|
|
int d = (int)(val - (r * 10));
|
|
val = r;
|
|
buf[n_buf++] = (char)(d + '0');
|
|
}
|
|
}
|
|
break;
|
|
case 16:
|
|
while (val != 0)
|
|
{
|
|
int d = (int)(val & 0x0f);
|
|
val >>= 4;
|
|
buf[n_buf++] = (char)((d < 10) ? (d + '0') : (d + hex_char));
|
|
}
|
|
break;
|
|
}
|
|
if ((n_prefix > 0) && (prefix[0] == '0'))
|
|
{
|
|
n_prefix = 0;
|
|
buf[n_buf++] = '0';
|
|
}
|
|
}
|
|
goto put_to_stream;
|
|
|
|
put_to_stream:
|
|
{
|
|
int n_pad = precision - n_buf;
|
|
if (flag & flag_zero)
|
|
{
|
|
if (n_pad < width - n_buf - n_prefix)
|
|
n_pad = width - n_buf - n_prefix;
|
|
}
|
|
if (n_pad > 0)
|
|
width -= n_pad;
|
|
width -= n_prefix + n_buf;
|
|
if (!(flag & flag_minus))
|
|
string_fill_char(&str, ' ', width);
|
|
while (n_prefix > 0)
|
|
string_put_char(&str, prefix[--n_prefix]);
|
|
string_fill_char(&str, '0', n_pad);
|
|
while (n_buf > 0)
|
|
string_put_char(&str, buf[--n_buf]);
|
|
if (flag & flag_minus)
|
|
string_fill_char(&str, ' ', width);
|
|
++s;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (str.len > 0)
|
|
*str.cur = '\0';
|
|
else if (len > 0)
|
|
str.base[len - 1] = '\0';
|
|
return str.cur - str.base;
|
|
}
|
|
|
|
#if defined(SDK_CW_WARNOFF_SAFESTRB)
|
|
#include <nitro/codereset.h>
|
|
#endif
|
|
|
|
|
|
|
|
//================================================================================
|
|
// DUMMY PRINT (stub for FINALROM)
|
|
//================================================================================
|
|
#ifdef SDK_FINALROM
|
|
#ifdef OS_Printf
|
|
#undef OS_Printf
|
|
#endif
|
|
void OS_Printf(const char *fmt, ...);
|
|
void OS_Printf(const char *fmt, ...)
|
|
{
|
|
#pragma unused( fmt )
|
|
}
|
|
#endif
|