/*---------------------------------------------------------------------------*
  Project:  TwlSDK - OS
  File:     os_argument.c

  Copyright 2005-2009 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.

  $Date:: 2009-06-17#$
  $Rev: 10762 $
  $Author: mizutani_nakaba $
 *---------------------------------------------------------------------------*/
#include <nitro/os.h>
#include <nitro/std/string.h>
#ifdef SDK_TWL
#include <twl/os/common/systemWork.h>
#endif

#define OSi_INIVALUE    0xffff

#ifndef OS_NO_ARGUMENT

#include <nitro/version_begin.h>
//---- This area is for argument string, and may be
//     modified from external tools.
static OSArgumentBuffer OSi_ArgumentBuffer = {
    OS_ARGUMENT_ID_STRING,
    OS_ARGUMENT_BUFFER_SIZE,
    {'\0', '\0'},
};
#include <nitro/version_end.h>

//---- pointer to current argument buffer
const char *sCurrentArgBuffer = &OSi_ArgumentBuffer.buffer[0];

static const char *match_opt(int optchar, const char *optstring);
#endif //ifndef OS_NO_ARGUMENT

//---- for TWL
#ifdef SDK_TWL
static u32                  sBufferState = OS_DELIVER_ARG_BUF_INVALID;
static OSDeliverArgInfo*    sBufferPtr = NULL;
static u8*                  sPtr;
static OSTitleId            sEncodedTitleId = 0;
#endif

static int OSi_GetArgc_core(const char* p);
static const char *OSi_GetArgv_core(const char *p, int n);


/*---------------------------------------------------------------------------*
  Name:         ( OSi_GetArgc_core )

  Description:  Get number of valid arguments.

  Arguments:    p : pointer to argument buffer

  Returns:      number of valid arguments.
 *---------------------------------------------------------------------------*/
static int OSi_GetArgc_core(const char* p)
{
    int     n = 0;
    for (; *p; p++, n++)
    {
        while (*p)
        {
            p++;
        }
    }
    return n;
}

/*---------------------------------------------------------------------------*
  Name:         OS_GetArgc

  Description:  Get number of valid arguments.
                This function is for debug.

  Arguments:    None

  Returns:      number of valid arguments.
                return 1 if no argument.
                return 0 if not set argument buffer.
 *---------------------------------------------------------------------------*/
#ifndef OS_NO_ARGC_AND_ARGV
int OS_GetArgc(void)
{
	return OSi_GetArgc_core( (const char *)sCurrentArgBuffer );
}
#endif


/*---------------------------------------------------------------------------*
  Name:         ( OSi_GetArgv_core )

  Description:  Get the pointer to the specified argument string.

  Arguments:    n : index of argument. n==1 means the first argument.

  Returns:      n must less than value of OS_GetArgc()
 *---------------------------------------------------------------------------*/
static const char *OSi_GetArgv_core(const char *p, int n)
{
    SDK_ASSERT(n >= 0);
	for (; *p && n > 0; p++, n--)
	{
		while (*p)
		{
			p++;
		}
    }
    return (*p) ? p : NULL;
}

/*---------------------------------------------------------------------------*
  Name:         OS_GetArgv

  Description:  Get the pointer to the specified argument string.
                This function is for debug.

  Arguments:    n : index of argument. n==1 means the first argument.
                    n must less than value of OS_GetArgc()

  Returns:      pointer to the specified argument string
 *---------------------------------------------------------------------------*/
#ifndef OS_NO_ARGC_AND_ARGV
const char* OS_GetArgv(int n)
{
	return OSi_GetArgv_core( (const char *)sCurrentArgBuffer, n );
}
#endif


/*---------------------------------------------------------------------------*
  Name:         OS_GetOpt

  Description:  getopt() like function to get command line options
  
  Arguments:    optstring  オプションキャラクタの列
                           NULL なら内部パラメータがリセットされる

  Returns:      オプション文字コード
                '?' なら不明なオプション文字コード
                -1  ならオプションが存在しない
 *---------------------------------------------------------------------------*/
#ifndef OS_NO_ARGUMENT
const char *OSi_OptArg = NULL;
int     OSi_OptInd = 1;
int     OSi_OptOpt = 0;

int OS_GetOpt(const char *optstring)
{
    static BOOL end_of_option = FALSE;
    int     optchar;
    const char *arg;
    const char *opt;
    const char *optarg;

    OSi_OptArg = NULL;
    OSi_OptOpt = 0;

    // optstring が NULL ならリセット
    if (optstring == NULL)
    {
        OSi_OptInd = 1;
        end_of_option = FALSE;
        return 0;
    }

    // コマンドライン引数取得
    arg = OS_GetArgv(OSi_OptInd);

    if (arg == NULL)
    {
        return -1;
    }

    if (optstring[0] == '-')           // Minus Mode
    {
        OSi_OptInd++;                  // 引数消費

        // '-' から始まらない場合は通常引数
        if (end_of_option || arg[0] != '-')
        {
            OSi_OptArg = arg;          // 通常引数も OptArg にセットされる．
            return 1;
        }

        // オプション解析
        optchar = arg[1];

        if (optchar == '-')            // '--' でオプション終了
        {
            end_of_option = TRUE;      // 次からは通常引数
            return OS_GetOpt(optstring);
        }
    }
    else                               // normal mode
    {
        // '-' から始まらない場合は通常引数
        if (end_of_option || arg[0] != '-')
        {
            return -1;                 // OptArg は NULL のまま
        }

        OSi_OptInd++;                  // 引数消費

        // オプション解析
        optchar = arg[1];

        if (optchar == '-')            // '--' でオプション終了
        {
            end_of_option = TRUE;      // 次からは通常引数
            return -1;
        }

    }

    opt = match_opt(optchar, optstring);

    if (opt == NULL)
    {
        OSi_OptOpt = optchar;          // 知らないオプション
        return '?';
    }

    if (opt[1] == ':')                 // OptArg の検索指定？
    {
        optarg = OS_GetArgv(OSi_OptInd);

        if (optarg == NULL || optarg[0] == '-')
        {
            if (opt[2] != ':')         // '::' でない？
            {
                OSi_OptOpt = optchar;  // OptArg が無い
                return '?';
            }
            // OptArg が無い
            // OSi_OptArg = NULL
        }
        else
        {
            OSi_OptArg = optarg;
            OSi_OptInd++;              // 引数消費
        }
    }
    return optchar;
}

static const char *match_opt(int optchar, const char *optstring)
{
    if (optstring[0] == '-' || optstring[0] == '+')
    {
        optstring++;
    }

    if (optchar != ':')
    {
        while (*optstring)
        {
            if (optchar == *optstring)
            {
                return optstring;
            }
            optstring++;
        }
    }
    return NULL;
}
#endif // ifndef OS_NO_ARGUMENT

/*---------------------------------------------------------------------------*
  Name:         OS_ConvertToArguments

  Description:  convert string data to arg binary
  
  Arguments:    str     : string
                cs      : character to separate
                buffer  : buffer to store
                bufSize : max buffer size
 
  Returns:      None.
 *---------------------------------------------------------------------------*/
#ifndef OS_NO_ARGUMENT
void OS_ConvertToArguments(const char *str, char cs, char *buffer, u32 bufSize)
{
    char   *p = buffer;
    char   *pEnd = buffer + bufSize;
    BOOL    isQuoted = FALSE;

    while (1)
    {
        //---- skip separater
        while (*str == cs && p < pEnd)
        {
            str++;
        }

        //---- store argument string
        while (*str && p < pEnd)
        {
            //---- check quote
            if (*str == '\"')
            {
                isQuoted = (isQuoted == FALSE);
                str++;
                continue;
            }

            //---- found separater
            else if (*str == cs && isQuoted == FALSE)
            {
                break;
            }

            *p++ = *str++;
        }

        //---- 1) reached to the buffer end
        if (p >= pEnd)
        {
            *(pEnd - 2) = '\0';
            *(pEnd - 1) = '\0';
            break;
        }

        //---- 2) reached to the string end
        if (*str == '\0')
        {
            while ((p + 1) >= pEnd)
            {
                p--;
            }
            *p++ = '\0';
            *p = '\0';
            break;
        }

        //---- 3) separater
        if (*str == cs)
        {
            *p++ = '\0';
        }
    }

    //---- end mark
    if (p < pEnd)
    {
        *p++ = '\0';
    }
}
#endif //ifndef OS_NO_ARGUMENT

/*---------------------------------------------------------------------------*
  Name:         OS_SetArgumentBuffer

  Description:  force to set argument buffer.
  
  Arguments:    buffer : argument buffer
 
  Returns:      None.
 *---------------------------------------------------------------------------*/
#ifndef OS_NO_ARGUMENT
void OS_SetArgumentBuffer(const char *buffer)
{
    sCurrentArgBuffer = buffer;
}
#endif //ifndef OS_NO_ARGUMENT

/*---------------------------------------------------------------------------*
  Name:         OS_GetArgumentBuffer

  Description:  get pointer to argument buffer.
  
  Arguments:    None.
 
  Returns:      pointer to argument buffer.
 *---------------------------------------------------------------------------*/
#ifndef OS_NO_ARGUMENT
const char *OS_GetArgumentBuffer(void)
{
    return sCurrentArgBuffer;
}
#endif //ifndef OS_NO_ARGUMENT


//================================================================================
// for TWL
//================================================================================
#ifdef SDK_TWL
/*---------------------------------------------------------------------------*
  Name:         OS_InitDeliverArgInfo

  Description:  initialize the argument delivery system for TWL
  
  Arguments:    binSize : buffer size for binary area.
 
  Returns:      None
 *---------------------------------------------------------------------------*/
void OS_InitDeliverArgInfo( OSDeliverArgInfo* info, int binSize )
{
    SDK_ASSERT( 2<=(OS_DELIVER_ARG_BUFFER_SIZE-binSize) && binSize>=0);
    SDK_ASSERT( info != NULL );

    sBufferPtr = info;

    //---- clear whole buffer
    MI_CpuClear8( sBufferPtr, HW_PARAM_DELIVER_ARG_SIZE );

    //---- set parameters
    sBufferState = OS_DELIVER_ARG_BUF_ACCESSIBLE | OS_DELIVER_ARG_BUF_WRITABLE;
    sBufferPtr->header.argBufferSize = (u16)(OS_DELIVER_ARG_BUFFER_SIZE - binSize);
    sBufferPtr->header.binarySize = 0;

    //---- init pointer
    sPtr = &sBufferPtr->buf[0];
    *sPtr = '\0';
    *(sPtr+1) = '\0';
}

/*---------------------------------------------------------------------------*
  Name:         OS_SetStringToDeliverArg

  Description:  write specified string as argument data
  
  Arguments:    str : string to write
 
  Returns:      OS_DELIVER_ARG_SUCCESS   ... success.
                OS_DELIVER_ARG_OVER_SIZE ... failed. (over buffer)
                OS_DELIVER_ARG_NOT_READY ... failed. (buffer is not writable)
 *---------------------------------------------------------------------------*/
int OS_SetStringToDeliverArg( const char* str )
{
    int length;

    //---- check buffer state
    if ( !(sBufferState & OS_DELIVER_ARG_BUF_WRITABLE) )
    {
        return OS_DELIVER_ARG_NOT_READY;
    }

    //---- check buffer over
    length = STD_StrLen( str );

    if ( length > sBufferPtr->header.argBufferSize - (sPtr - &sBufferPtr->buf[0]) - 2)
    {
        return OS_DELIVER_ARG_OVER_SIZE;
    }

    //---- copy string
    (void)STD_StrCpy( (char*)sPtr, str );
    sPtr += length;
    *sPtr++ = '\0';
    *sPtr = '\0';

    //---- return result
    return OS_DELIVER_ARG_SUCCESS;
}


/*---------------------------------------------------------------------------*
  Name:         OS_SetBinaryToDeliverArg

  Description:  write sprcified binary 
  
  Arguments:    bin  : pointer of binary
                size : binary size
 
  Returns:      OS_DELIVER_ARG_SUCCESS   ... success.
                OS_DELIVER_ARG_OVER_SIZE ... failed. (over buffer)
                OS_DELIVER_ARG_NOT_READY ... failed. (buffer is not writable)
 *---------------------------------------------------------------------------*/
int OS_SetBinaryToDeliverArg( const void* bin, int size )
{
    u8* dest = &sBufferPtr->buf[ sBufferPtr->header.argBufferSize + sBufferPtr->header.binarySize ];

    //---- check buffer state
    if ( !(sBufferState & OS_DELIVER_ARG_BUF_WRITABLE) )
    {
        return OS_DELIVER_ARG_NOT_READY;
    }

    //---- check buffer over
    if ( size > OS_DELIVER_ARG_BUFFER_SIZE - sBufferPtr->header.argBufferSize - sBufferPtr->header.binarySize )
    {
        return OS_DELIVER_ARG_OVER_SIZE;
    }

    //---- write binary data to buffer
    MI_CpuCopy8( bin, dest, (u32)size );
    sBufferPtr->header.binarySize += (u16)size;

    //---- return result
    return OS_DELIVER_ARG_SUCCESS;
}

/*---------------------------------------------------------------------------*
  Name:         OS_ConvertStringToDeliverArg

  Description:  convert string to arguments
  
  Arguments:    str : string
                cs  : character to separate
 
  Returns:      OS_DELIVER_ARG_SUCCESS    ... success 
                OS_DELIVER_ARG_OVER_SIZE  ... failed. (over buffer)
                OS_DELIVER_ARG_NOT_READY  ... failed. (buffer is not writable)
 *---------------------------------------------------------------------------*/
int OS_ConvertStringToDeliverArg(const char *str, char cs)
{
    int length;
    const char* endp;

    //---- check buffer state
    if ( !(sBufferState & OS_DELIVER_ARG_BUF_WRITABLE) )
    {
        return OS_DELIVER_ARG_NOT_READY;
    }

    while (1)
    {
        //---- skip separater
        while ( *str == cs )
        {
            str++;
        }

        //---- check string end
        if ( ! *str )
        {
            break;

        }

        //---- search separator
        endp = str;
        while ( *endp != cs && *endp != '\0' )
        {
            endp++;
        }
        length = endp - str;

        //---- check buffer over
        if ( length > sBufferPtr->header.argBufferSize - (sPtr - &sBufferPtr->buf[0]) - 2)
        {
            return OS_DELIVER_ARG_OVER_SIZE;
        }

        //---- copy string
        while( str != endp )
        {
            *sPtr ++ = *(u8*)str ++;
        }
        *sPtr ++ = '\0';
        *sPtr = '\0';
    }

    return OS_DELIVER_ARG_SUCCESS;
}

/*---------------------------------------------------------------------------*
  Name:         OS_EncodeDeliverArg

  Description:  Encode argument buffer.
  
  Arguments:    None
 
  Returns:      OS_DELIVER_ARG_SUCCESS    ... success 
                OS_DELIVER_ARG_NOT_READY  ... failed. (buffer is not accesible)
 *---------------------------------------------------------------------------*/
int OS_EncodeDeliverArg(void)
{
    //---- check buffer state
    if ( !(sBufferState & OS_DELIVER_ARG_BUF_ACCESSIBLE) )
    {
        return OS_DELIVER_ARG_NOT_READY;
    }
    
    //---- set makerCode, titleId
    sBufferPtr->header.makerCode = OS_GetMakerCode();
    sBufferPtr->header.titleId = OS_GetTitleId();

    //---- set flag
    sBufferPtr->header.flag = OS_DELIVER_ARG_ENCODE_FLAG | OS_DELIVER_ARG_VALID_FLAG;

    //---- set encoded titleId
    sEncodedTitleId = sBufferPtr->header.titleId;

    //---- calculate crc
    sBufferPtr->header.crc = 0;
    sBufferPtr->header.crc = SVC_GetCRC16( OSi_INIVALUE, (const void*)sBufferPtr, sizeof(OSDeliverArgInfo) );

    //---- copy to HW_PARAM_DELIVER_ARG
    MI_CpuCopy8( sBufferPtr, (void*)HW_PARAM_DELIVER_ARG, sizeof(OSDeliverArgInfo) );

    //---- clearArea
    MI_CpuClear8( sBufferPtr, sizeof(OSDeliverArgInfo) );

    //---- buffer state
    sBufferState = OS_DELIVER_ARG_BUF_INVALID;

    return OS_DELIVER_ARG_SUCCESS;
}

/*---------------------------------------------------------------------------*
  Name:         OS_DecodeDeliverArg

  Description:  decode to work buffer from HW_PARAM_DELIVER_ARG
  
  Arguments:    None
 
  Returns:      OS_DELIVER_ARG_SUCCESS    ... success
                OS_DELIVER_ARG_NOT_READY  ... not ready
                OS_DELIVER_ARG_INVALID    ... invalid CRC check
 *---------------------------------------------------------------------------*/
int OS_DecodeDeliverArg(void)
{
    //----check if deliver arg contains valid data
    if ( !OS_IsValidDeliverArg() )
    {
        return OS_DELIVER_ARG_NOT_READY;
    }
    
    //----check buffer
    if ( ! sBufferPtr )
    {
        return OS_DELIVER_ARG_NOT_READY;
    }

    //---- copy from HW_PARAM_DELIVER_ARG
    MI_CpuCopy8( (void*)HW_PARAM_DELIVER_ARG, sBufferPtr, sizeof(OSDeliverArgInfo) );

    //---- crc check
    {
        u16 crc = sBufferPtr->header.crc;
        sBufferPtr->header.crc = 0;
        sBufferPtr->header.crc = SVC_GetCRC16( OSi_INIVALUE, (const void*)sBufferPtr, sizeof(OSDeliverArgInfo) );
        if ( crc != sBufferPtr->header.crc )
        {
            MI_CpuClear8( sBufferPtr, sizeof(OSDeliverArgInfo) );
            OS_SetDeliverArgStateInvalid();
            return OS_DELIVER_ARG_BUF_INVALID;
        }
    }

    //---- unset encode flag
    sBufferPtr->header.flag &= ~OS_DELIVER_ARG_ENCODE_FLAG;

    //---- buffer state
    sBufferState = OS_DELIVER_ARG_BUF_ACCESSIBLE;

    return OS_DELIVER_ARG_SUCCESS;
}

/*---------------------------------------------------------------------------*
  Name:         OS_GetDeliverArgState

  Description:  get deliber arg state
  
  Arguments:    None
 
  Returns:      state.
                one of the following:
                  OS_DELIVER_ARG_BUF_INVALID
                  OS_DELIVER_ARG_BUF_ACCESSIBLE
                  OS_DELIVER_ARG_BUF_ACCESSIBLE | OS_DELIVER_ARG_BUF_WRITABLE
 *---------------------------------------------------------------------------*/
u32 OS_GetDeliverArgState(void)
{
    return sBufferState;
}

/*---------------------------------------------------------------------------*
  Name:         OSi_SetDeliverArgState

  Description:  set deliber arg state
  
  Arguments:    state.
                one of the following:
                  OS_DELIVER_ARG_BUF_INVALID
                  OS_DELIVER_ARG_BUF_ACCESSIBLE
                  OS_DELIVER_ARG_BUF_ACCESSIBLE | OS_DELIVER_ARG_BUF_WRITABLE

  Returns:      None
 *---------------------------------------------------------------------------*/
void OSi_SetDeliverArgState(u32 state)
{
    sBufferState = state;
}

/*---------------------------------------------------------------------------*
  Name:         OS_SetDeliverArgStateInvalid

  Description:  set OS_DELIVER_ARG_BUF_INVALID to deliber arg state
  
  Arguments:    None
 
  Returns:      None
 *---------------------------------------------------------------------------*/
void OS_SetDeliverArgStateInvalid( void )
{
    sBufferState = OS_DELIVER_ARG_BUF_INVALID;
}

/*---------------------------------------------------------------------------*
  Name:         OS_GetBinarySizeFromDeliverArg

  Description:  read binary size
  
  Arguments:    None
 
  Returns:      0> ... size
                -1 ... work area not ready
 *---------------------------------------------------------------------------*/
int OS_GetBinarySizeFromDeliverArg(void)
{
    if ( !(sBufferState & OS_DELIVER_ARG_BUF_ACCESSIBLE) )
    {
        return -1;
    }

    return sBufferPtr->header.binarySize;
}

/*---------------------------------------------------------------------------*
  Name:         OS_GetBinaryFromDeliverArg

  Description:  read binary data
  
  Arguments:    buffer  : pointer of binary
                size    : pointer of binary size
                maxSize : max size
 
  Returns:      OS_DELIVER_ARG_SUCCESS   ... success.
                OS_DELIVER_ARG_OVER_SIZE ... success but buffer over.
                OS_DELIVER_ARG_NOT_READY ... 
 *---------------------------------------------------------------------------*/
int OS_GetBinaryFromDeliverArg( void* buffer, int* size, int maxSize )
{
    int retval;
    int copySize;

    //---- check buffer state
    if ( !(sBufferState & OS_DELIVER_ARG_BUF_ACCESSIBLE) )
    {
        return OS_DELIVER_ARG_NOT_READY;
    }

    //---- check buffer over
    if ( maxSize < sBufferPtr->header.binarySize )
    {
        retval = OS_DELIVER_ARG_OVER_SIZE;
        copySize = maxSize;
    }
    else
    {
        retval = OS_DELIVER_ARG_SUCCESS;
        copySize = sBufferPtr->header.binarySize;
    }

    //---- read binary data
    MI_CpuCopy8( &sBufferPtr->buf[sBufferPtr->header.argBufferSize], buffer, (u32)copySize );
    if ( size )
    {
        *size = copySize;
    }

    return retval;
}

/*---------------------------------------------------------------------------*
  Name:         OS_GetTitleIdFromDeliverArg

  Description:  get title ID
  
  Arguments:    None
 
  Returns:      title ID.
                if not accessible, return 0
 *---------------------------------------------------------------------------*/
OSTitleId OS_GetTitleIdFromDeliverArg( void )
{
    return (sBufferState & OS_DELIVER_ARG_BUF_ACCESSIBLE)? sBufferPtr->header.titleId: 0;
}

/*---------------------------------------------------------------------------*
  Name:         OS_GetGameCodeFromDeliverArg

  Description:  get game code
  
  Arguments:    None
 
  Returns:      game code
                if not accessible, return 0
 *---------------------------------------------------------------------------*/
u32 OS_GetGameCodeFromDeliverArg( void )
{
    return (sBufferState & OS_DELIVER_ARG_BUF_ACCESSIBLE)? *(u32*)(&sBufferPtr->header.titleId): 0;
}

/*---------------------------------------------------------------------------*
  Name:         OS_GetMakerCodeFromDeliverArg

  Description:  get maker code
  
  Arguments:    None
 
  Returns:      maker code
                if not accessible, return 0
 *---------------------------------------------------------------------------*/
u16 OS_GetMakerCodeFromDeliverArg( void )
{
    return (u16)((sBufferState & OS_DELIVER_ARG_BUF_ACCESSIBLE)? sBufferPtr->header.makerCode: 0);
}

/*---------------------------------------------------------------------------*
  Name:         OS_IsValidDeliverArg

  Description:  check if deliver arg contains valid data
  
  Arguments:    None
 
  Returns:      TRUE if valid
                FALSE if not valid
 *---------------------------------------------------------------------------*/
BOOL OS_IsValidDeliverArg( void )
{
    // [TODO:]もう少し信頼できる検証処理を
    OSDeliverArgInfo* p = (OSDeliverArgInfo*)HW_PARAM_DELIVER_ARG;

    return (p->header.flag & OS_DELIVER_ARG_VALID_FLAG) ? TRUE : FALSE;
}

/*---------------------------------------------------------------------------*
  Name:         OS_IsDeliverArgEncoded

  Description:  get titleId that is contained in last encoded deliverArg
  
  Arguments:    None
 
  Returns:      TRUE  if deliverArg has been encoded
                FALSE if deliverArg has never been encoded since application was
                launched
 *---------------------------------------------------------------------------*/
BOOL OS_IsDeliverArgEncoded( void )
{
    OSDeliverArgInfo* p = (OSDeliverArgInfo*)HW_PARAM_DELIVER_ARG;
    return (p->header.flag & (OS_DELIVER_ARG_ENCODE_FLAG | OS_DELIVER_ARG_VALID_FLAG)) ? TRUE : FALSE;
}

/*---------------------------------------------------------------------------*
  Name:         OS_GetTitleIdLastEncoded

  Description:  get titleId that is contained in last encoded deliverArg
  
  Arguments:    None
 
  Returns:      TitleID if deliverArg has been encoded
                0 if deliverArg has never been encoded since application was
                launched
 *---------------------------------------------------------------------------*/
OSTitleId OS_GetTitleIdLastEncoded( void )
{
	return sEncodedTitleId;
}

/*---------------------------------------------------------------------------*
  Name:         OS_SetSysParamToDeliverArg

  Description:  set sysParam to deliverArg
  
  Arguments:    param: parameter to set
 
  Returns:      None
 *---------------------------------------------------------------------------*/
int OS_SetSysParamToDeliverArg( u16 param )
{
    if ( !(sBufferState & OS_DELIVER_ARG_BUF_WRITABLE) )
    {
        return OS_DELIVER_ARG_NOT_READY;
    }

    sBufferPtr->header.sysParam = param;
    return OS_DELIVER_ARG_SUCCESS;
}

/*---------------------------------------------------------------------------*
  Name:         OS_GetSysParamFromDeliverArg

  Description:  get sysParam from deliverArg
  
  Arguments:    None
 
  Returns:      parameter. 0 if FAIL.
 *---------------------------------------------------------------------------*/
u16 OS_GetSysParamFromDeliverArg( void )
{
    if ( !(sBufferState & OS_DELIVER_ARG_BUF_ACCESSIBLE) )
    {
        return 0;
    }

    return sBufferPtr->header.sysParam;
}

/*---------------------------------------------------------------------------*
  Name:         OS_GetDeliverArgc

  Description:  Get number of valid arguments in deliverArg.

  Arguments:    None

  Returns:      number of valid arguments.
                return 1 if no argument.
                return 0 if buffer is not prepared.
 *---------------------------------------------------------------------------*/
int OS_GetDeliverArgc(void)
{
    if ( sBufferPtr && sBufferState == OS_DELIVER_ARG_BUF_ACCESSIBLE )
    {
		return OSi_GetArgc_core( (const char *)sBufferPtr->buf ) + 1;
    }

    return 0;
}

/*---------------------------------------------------------------------------*
  Name:         OS_GetDeliverArgv

  Description:  Get the pointer to the specified argument string in deliverArg.

  Arguments:    n : index of argument. n==1 means the first argument.
                    n must less than value of OS_GetDeliverArgc()

  Returns:      pointer of string
 *---------------------------------------------------------------------------*/
const char *OS_GetDeliverArgv(int n)
{
    static const char *procName = "main";
    SDK_ASSERT(n >= 0);

    if ( sBufferPtr && sBufferState == OS_DELIVER_ARG_BUF_ACCESSIBLE )
    {   
		return (n==0)? procName: OSi_GetArgv_core( (const char *)sBufferPtr->buf, n-1 );
    }

    return NULL;
}
#endif //ifdef SDK_TWL
