Home

Resume

Blog

Teikitu


/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/*  »Project«   Teikitu Gaming System (TgS) (∂)
    »File«      TgS Common - Global.c
    »Author«    Andrew Aye (EMail: mailto:andrew.aye@gmail.com, Web: http://www.andrewaye.com)
    »Version«   4.51 / »GUID« A9981407-3EC9-42AF-8B6F-8BE6DD919615                                                                                                        */
/*   -------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
/*  Copyright: © 2002-2017, Andrew Aye.  All Rights Reserved.
    This software is free for non-commercial use.  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
      following conditions are met:
        Redistribution of source code must retain this copyright notice, this list of conditions and the following disclaimers.
        Redistribution in binary form must reproduce this copyright notice, this list of conditions and the following disclaimers in the documentation and other materials
          provided with the distribution.
    The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
    The intellectual property rights of the algorithms used reside with Andrew Aye.
    You may not use this software, in whole or in part, in support of any commercial product without the express written consent of the author.
    There is no warranty or other guarantee of fitness of this software for any purpose. It is provided solely "as is".                                                   */
/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/* == Common ============================================================================================================================================================ */

/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  Private Data                                                                                                                                                          */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

#if TgCOMPILE_THREAD

TgUINT32                                    g_auiTR_Thread_Stack[KTgMAX_THREAD_ENTRIES];
TgPLATFORM_THREAD_FCN                       g_afnTR_Thread_Function[KTgMAX_THREAD_ENTRIES];
TgUINTPTR                                   g_auiTR_Thread_Param[KTgMAX_THREAD_ENTRIES];
ETgTHREAD_PRIORITY                          g_aenTR_Thread_Priority[KTgMAX_THREAD_ENTRIES];
TgOS_THREAD                                 g_aTR_Thread[KTgMAX_THREAD_ENTRIES];
TgTHREAD_ID                                 g_atiTR_Thread[KTgMAX_THREAD_ENTRIES];
STg2_UTM_SN_ISO                             g_sTR_Lock;

#if TgCOMPILE_THREAD_INFO
CP_TgCHAR                                   g_aszTR_Name[KTgMAX_THREAD_ENTRIES];
#endif

/*# TgCOMPILE_THREAD */
#endif




/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  File Local Data */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

static TgCHAR                               s_szCmdLN[KTgMAX_CMD_LINE_SIZE];
static CP_TgCHAR                            s_aszCmd[KTgMAX_CMD_LINE_COUNT];
static TgSINT32                             s_niCmd;
static TgFLOAT32                            s_fCurrent;
static TgSINT32                             s_iCurrent;

static TgUINT32                             s_uiVersion;
static TgFLOAT32                            s_fFrameTime;
static TgUINT32                             s_bfGlobal;
static volatile TgATOMIC_SINT64             s_uiUnique;
static ETgMODULE_STATE                      s_enGlobal_State;

#if !TgCOMPILE_64BIT_ATOMIC
static STg1_MP_CS                           s_sWin32Lock;
#endif




/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  Public Functions                                                                                                                                                      */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

/* ---- tgGB_Init ------------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgGB_Init( TgVOID )
{
    TgSINTPTR                           iFile;
#if TgCOMPILE_THREAD
    TgSINT32                            iIndex;
#endif

    s_enGlobal_State = ETgMODULE_STATE__INITIALIZING;

    s_fCurrent                          = 0.0F;
    s_iCurrent                          = 0;

    s_uiVersion                         = TGS_CORE_VERSION;
    s_fFrameTime                        = 0.0F;
    s_uiUnique                          = 0ULL;

    memset( s_szCmdLN, 0x00, sizeof( s_szCmdLN ) );
    memset( (P_TgVOID)s_aszCmd, 0x00, sizeof( s_aszCmd ) );

    s_niCmd                             = 0;

#if TgCOMPILE_THREAD
    memset( g_auiTR_Thread_Stack, 0xFF, sizeof( g_auiTR_Thread_Stack ) );
    memset( g_afnTR_Thread_Function, 0x0, sizeof( g_afnTR_Thread_Function ) );
    memset( g_auiTR_Thread_Param, 0xFF, sizeof( g_auiTR_Thread_Param ) );
    memset( g_aenTR_Thread_Priority, 0xFF, sizeof( g_aenTR_Thread_Priority ) );
    memset( g_aTR_Thread, 0x0, sizeof( g_aTR_Thread ) );
    for (iIndex = 0; iIndex < (TgSINT32)TgARRAY_COUNT(g_atiTR_Thread); ++iIndex)
    {
        g_atiTR_Thread[iIndex] = KTgTHREAD_ID__INVALID;
    };

    tgCM_UTM_SN_Init( &g_sTR_Lock.m_sLock );

#if TgCOMPILE_THREAD_INFO
    memset( (P_TgVOID)g_aszTR_Name, 0xFF, sizeof( g_aszTR_Name ) );
#endif
    
/*# TgCOMPILE_THREAD */
#endif

#if !defined(TgCOMPILE_FORCE_ANSI)
    if (TgFAILED(tgGB_Init_OS()))
    {
        return (KTgE_FAIL);
    };
/*# !defined(TgCOMPILE_FORCE_ANSI) */
#endif

#if !TgCOMPILE_64BIT_ATOMIC
    tgCM_MP_CS_Init( &s_sWin32Lock );
#endif

    tgTM_Init();

    do
    {
        if (TgFAILED( tgCN_Init() ))
            break;
        if (TgFAILED( tgCN_Boot() ))
            break;
        if (TgFAILED(tgMM_Init_MGR()))
            break;
        if (TgFAILED(tgSM_Init_MGR()))
            break;
        if (TgFAILED(tgSM_Boot_MGR()))
            break;

        /* Look for additional command line arguments in a flat file */
        tgSZ_Append( s_szCmdLN, KTgMAX_CMD_LINE_SIZE, TgT(" ") );
        if (tgIO_File_Exists( TgT("command_line.txt") ) && TgSUCCEEDED( tgIO_File_Open( &iFile, TgT("command_line.txt"), ETgFILE_IO_ACCESS__READ | ETgFILE_IO_ACCESS__SHARED ) ))
        {
            TgSIZE                              nuiLength = tgSZ_Length( s_szCmdLN );
            TgSIZE                              niData = KTgMAX_CMD_LINE_SIZE - 1 - nuiLength;

        #if defined(TgCOMPILE_WIDE_CHAR) && TgCOMPILE_WIDE_CHAR
            TgANSICHAR                          szAnsiText[KTgMAX_CMD_LINE_SIZE];

            niData = tgIO_File_Read( iFile, szAnsiText, niData );
            tgIO_File_Close( iFile );
            szAnsiText[niData] = 0;

            tgSZ_PrintF( s_szCmdLN + nuiLength, KTgMAX_CMD_LINE_SIZE, TgT("%S"), szAnsiText );
        /*# defined(TgCOMPILE_WIDE_CHAR) && TgCOMPILE_WIDE_CHAR */
        #else
            niData = tgIO_File_Read( iFile, s_szCmdLN + nuiLength, niData );
            tgIO_File_Close( iFile );
            s_szCmdLN[nuiLength + niData] = 0;
        /*# defined(TgCOMPILE_WIDE_CHAR) && TgCOMPILE_WIDE_CHAR */
        #endif
        };

        if (0 != s_szCmdLN[0])
        {
            s_niCmd = (TgSINT32)tgGB_Parse_Command_Line( s_aszCmd, KTgMAX_CMD_LINE_COUNT, s_szCmdLN );
        };

    #if defined(TgCOMPILE_PROFILE) && TgCOMPILE_PROFILE
        if (TgFAILED(tgPF_Init()))
            break;
        if (TgFAILED(tgPF_Boot()))
            break;
    /*# defined(TgCOMPILE_PROFILE) && TgCOMPILE_PROFILE */
    #endif

        if (TgFAILED(tgJM_Init_MGR()))
            break;

        if (TgFAILED(tgEM_Init_MGR()))
            break;

        s_enGlobal_State = ETgMODULE_STATE__INITIALIZED;
        return (KTgS_OK);

    }
    while (0);

    TgERROR(TgFALSE);
    tgGB_Free();
    return (KTgE_FAIL);
}


/* ---- tgGB_Boot ------------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgGB_Boot( TgVOID )
{
    /*  Quite obviously we cant use the memory manage to allocate memory at this point.  Use the C-standard allocator for these objects.  They should all be extremely small */
    /* and have no effect (should report back 100% error state). The reason for these is to allow any sub-system to die gracefully during initialization, giving back an */
    /* appropriate error rather than possible null-dereferences etc. */

    TgERROR(ETgMODULE_STATE__INITIALIZED == s_enGlobal_State || ETgMODULE_STATE__STOPPED == s_enGlobal_State);
    s_enGlobal_State = ETgMODULE_STATE__BOOTING;

    do
    {
    #if !defined(TgCOMPILE_FORCE_ANSI)
        if (TgFAILED(tgGB_Boot_OS()))
            break;
    /*# !defined(TgCOMPILE_FORCE_ANSI) */
    #endif

        if (TgFAILED(tgJM_Boot_MGR()))
            break;

        if (TgFAILED(tgEM_Boot_MGR()))
            break;

        if (tgGB_CMD_Query_Argument_Index( TgT("-//stat/boot/command") ) >= 0)
        {
        #if TgS_STAT_COMMON
            tgGB_Stats( &g_sOutCon );
        /*# TgS_STAT_COMMON */
        #endif
            tgIO_PrintF( &g_sOutCon, TgT("\n") );
        };

    #if !defined(TgCOMPILE_FORCE_ANSI)
        if (tgGB_CMD_Query_Argument_Index( TgT("-//stat/boot/info") ) >= 0)
        {
            tgSI_Stats( &g_sOutCon );
        };
    /*# !defined(TgCOMPILE_FORCE_ANSI) */
    #endif

        if (tgGB_CMD_Query_Argument_Index( TgT("-//stat/boot/console") ) >= 0)
        {
            tgCN_Print_Commands( &g_sOutCon );
        };

        s_enGlobal_State = ETgMODULE_STATE__BOOTED;
        return (KTgS_OK);

    }
    while (0);

    TgERROR(TgFALSE);
    tgGB_Stop();
    return (KTgE_FAIL);
}


/* ---- tgGB_Stop ------------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgGB_Stop( TgVOID )
{
    TgERROR(ETgMODULE_STATE__BOOTED == s_enGlobal_State);
    s_enGlobal_State = ETgMODULE_STATE__STOPPING;

    tgEM_Stop_MGR();
    tgJM_Stop_MGR();
#if !defined(TgCOMPILE_FORCE_ANSI)
    tgGB_Stop_OS();
#endif
    s_enGlobal_State = ETgMODULE_STATE__STOPPED;
}


/* ---- tgGB_Free ------------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgGB_Free( TgVOID )
{
#if TgCOMPILE_THREAD
    TgSINT32                            iIndex;
#endif

    TgERROR(ETgMODULE_STATE__STOPPED == s_enGlobal_State || ETgMODULE_STATE__INITIALIZED == s_enGlobal_State);
    s_enGlobal_State = ETgMODULE_STATE__FREEING;

    tgEM_Free_MGR();
    tgJM_Free_MGR();
#if TgCOMPILE_PROFILE
    tgPF_Stop();
    tgPF_Free();
/*# TgCOMPILE_PROFILE */
#endif

    tgCN_Stop();
    tgCN_Free();
    tgSM_Stop_MGR();
    tgSM_Free_MGR();
    tgMM_Free_MGR();

#if !defined(TgCOMPILE_FORCE_ANSI)
    tgGB_Free_OS();
#endif

    memset( s_szCmdLN, 0x00, sizeof( s_szCmdLN ) );
    memset( (P_TgVOID)s_aszCmd, 0x00, sizeof( s_aszCmd ) );

#if TgCOMPILE_THREAD
    for (iIndex = 1; iIndex < (TgSINT32)TgARRAY_COUNT( g_atiTR_Thread ); ++iIndex)
    {
        TgERROR(TgTRUE != tgTHREAD_ID_Is_Valid( g_atiTR_Thread[iIndex] ));
    };
    TgERROR(TgTRUE == tgTHREAD_ID_Is_Valid( g_atiTR_Thread[iIndex] ));
/*# TgCOMPILE_THREAD */
#endif

#if !TgCOMPILE_64BIT_ATOMIC
    tgCM_MP_CS_Free( &s_sWin32Lock );
#endif

    s_enGlobal_State = ETgMODULE_STATE__FREED;
}


/* ---- tgGB_Update ----------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgGB_Update( C_TgFLOAT32 fDT )
{
    TgRESULT                            iResult = KTgS_OK;

    iResult |= tgMM_Update_MGR( fDT );
    iResult |= tgSM_Update_MGR( fDT );
    iResult |= tgEM_Update_MGR( fDT );
    iResult |= tgCN_Update( fDT );
#if TgCOMPILE_PROFILE
    iResult |= tgPF_Update( fDT );
#endif

    TgERROR(KTgS_OK == iResult);
    return (iResult);
}


/* ---- tgGB_Query_Init ------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgGB_Query_Init( TgVOID )
{
    return (ETgMODULE_STATE__INITIALIZED <= s_enGlobal_State && s_enGlobal_State <= ETgMODULE_STATE__STOPPED ? TgTRUE : TgFALSE);
}


/* ---- tgGB_Query_Boot ------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgGB_Query_Boot( TgVOID )
{
    return (ETgMODULE_STATE__BOOTED == s_enGlobal_State ? TgTRUE : TgFALSE);
}


/* ---- tgGB_Query_Fixed_Memory ----------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSIZE tgGB_Query_Fixed_Memory( TgVOID )
{
    return (0
        #if TgCOMPILE_THREAD
             + sizeof( g_auiTR_Thread_Stack )
             + sizeof( g_afnTR_Thread_Function )
             + sizeof( g_auiTR_Thread_Param )
             + sizeof( g_aenTR_Thread_Priority )
             + sizeof( g_aTR_Thread )
             + sizeof( g_atiTR_Thread )
             + sizeof( g_sTR_Lock )
        #if TgCOMPILE_THREAD_INFO
            + sizeof( g_aszTR_Name )
        #endif
        #endif
             + sizeof( s_szCmdLN )
             + sizeof( s_aszCmd )
             + sizeof( s_niCmd )
             + sizeof( s_fCurrent )
             + sizeof( s_iCurrent )
             + sizeof( s_uiVersion )
             + sizeof( s_fFrameTime )
             + sizeof( s_bfGlobal )
             + sizeof( s_uiUnique )
             + sizeof( s_enGlobal_State )
     #if !TgCOMPILE_64BIT_ATOMIC
             + sizeof( s_sWin32Lock )
     #endif
    );
}


/* ---- tgGB_Stats ------------------------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
#if TgS_STAT_COMMON
TgVOID tgGB_Stats( P_STg2_Output UNUSED_PARAM psOutput )
{
    TgSINT32                            iIndex;

    for (iIndex = 0; iIndex < tgGB_CMD_Query_Argument_Count(); ++iIndex)
    {
        tgIO_PrintF( &g_sOutCon, TgT("% 21.21s(% 2d): %s\n"), TgT("Cmd Line Arg"), iIndex, tgGB_CMD_Query_Argument( iIndex ) );
    };
}
/*# TgS_STAT_COMMON */
#endif


/* ---- tgGB_CMD_Set_Command_Line --------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgGB_CMD_Set_Command_Line( CPCU_TgCHAR szCmdLN )
{
    if (nullptr == szCmdLN)
    {
        s_szCmdLN[0] = 0;
    }
    else
    {
        tgSZ_Copy( s_szCmdLN, KTgMAX_CMD_LINE_SIZE, szCmdLN );
    }
}


/* ---- tgGB_CMD_Query_Argument_Count ----------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSINT32 tgGB_CMD_Query_Argument_Count( TgVOID )
{
    return (s_niCmd);
}


/* ---- tgGB_CMD_Query_Argument ----------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
CP_TgCHAR tgGB_CMD_Query_Argument( C_TgSINT32 uiArg )
{
    return (uiArg >= 0 && uiArg < s_niCmd ? s_aszCmd[uiArg] : nullptr);
}


/* ---- tgGB_CMD_Query_Argument_Index ----------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSINT32 tgGB_CMD_Query_Argument_Index( CPC_TgCHAR pszArgument )
{
    TgSINT32                            uiIndex;

    TgPARAM_CHECK(nullptr != pszArgument);

    for (uiIndex = 0; uiIndex < s_niCmd; ++uiIndex)
    {
        if (0 == tgSZ_Compare( s_aszCmd[uiIndex], pszArgument ))
        {
            return (uiIndex);
        };
    };

    return (-1);
}


/* ---- tgGB_CMD_Push_Argument ------------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgGB_CMD_Push_Argument( CPC_TgCHAR pszArgument )
{
    tgSZ_AppendF( s_szCmdLN, KTgMAX_CMD_LINE_SIZE, TgT( " %s " ), pszArgument );
    s_niCmd = (TgSINT32)tgGB_Parse_Command_Line( s_aszCmd, KTgMAX_CMD_LINE_COUNT, s_szCmdLN );
}


/* ---- tgGB_Reset_Frame_Time ------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgGB_Reset_Frame_Time( TgVOID )
{
    s_fFrameTime = 0.0F;
    s_fCurrent = 0.0F;
    s_iCurrent = 0;
}


/* ---- tgGB_Set_Frame_Time --------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgGB_Set_Frame_Time( C_TgFLOAT32 fTime )
{
    TgERROR(TgTRUE != tgPM_NAN_F32( fTime ));
    s_fFrameTime = 0.0F;
    s_fCurrent = fTime;
}


/* ---- tgGB_Inc_Frame_Time --------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgGB_Inc_Frame_Time( C_TgFLOAT32 fTime )
{
    TgERROR(TgTRUE != tgPM_NAN_F32( fTime ));
    s_fFrameTime = fTime;
    s_fCurrent += fTime;
    ++s_iCurrent;
}


/* ---- tgGB_Set_Unicode ------------------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgGB_Set_Unicode( C_TgBOOL bFlag )
{
    tgBF_Set_Flag_U32( &s_bfGlobal, 0, bFlag );
}


/* ---- tgGB_Set_Client ------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgGB_Set_Client( C_TgBOOL bFlag )
{
    tgBF_Set_Flag_U32( &s_bfGlobal, 1, bFlag );
}


/* ---- tgGB_Set_Server ------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgGB_Set_Server( C_TgBOOL bFlag )
{
    tgBF_Set_Flag_U32( &s_bfGlobal, 2, bFlag );
}


/* ---- tgGB_Set_Console_HW --------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgGB_Set_Console_HW( C_TgBOOL bFlag )
{
    tgBF_Set_Flag_U32( &s_bfGlobal, 3, bFlag );
}


/* ---- tgGB_Set_Free_On_Quit ------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgGB_Set_Free_On_Quit( C_TgBOOL bFlag )
{
    tgBF_Set_Flag_U32( &s_bfGlobal, 4, bFlag );
}


/* ---- tgGB_Get_Unique_Name -------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgGB_Get_Unique_Name( PCU_TgCHAR szDest, C_TgUINT32 nuiDest )
{
    TgUINT64                            uiUnique, uiLength;
    TgCHAR                              szNumber[32];

#if TgCOMPILE_64BIT_ATOMIC
    uiUnique = (TgUINT64)tgAM64_INC( &s_uiUnique );
#else
    tgCM_MP_CS_Enter_Block( &s_sWin32Lock );
    uiUnique = s_uiUnique++;
    tgCM_MP_CS_Exit( &s_sWin32Lock );
#endif

    tgSZ_From_U64( szNumber, 32, uiUnique );
    uiLength = tgSZ_Length( szNumber );

    if (uiLength + 12 <= nuiDest)
    {
        tgSZ_Copy( szDest, nuiDest, TgTEXT("UniqueName") );
        tgSZ_Append( szDest, nuiDest, szNumber );
        return (TgTRUE);
    };

    return (TgFALSE);
}


/* ---- tgGB_Query_Frame_Time ------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgFLOAT32 tgGB_Query_Frame_Time( TgVOID )
{
    return (s_fFrameTime);
}


/* ---- tgGB_Query_Total_Frame ------------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSINT32 tgGB_Query_Total_Frame( TgVOID )
{
    return (s_iCurrent);
}


/* ---- tgGB_Query_Total_Time ------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgFLOAT32 tgGB_Query_Total_Time( TgVOID )
{
    return (s_fCurrent);
}


/* ---- tgGB_Query_Unicode ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgGB_Query_Unicode( TgVOID )
{
    return (tgBF_Query_Flag_U32( &s_bfGlobal, 0 ));
}


/* ---- tgGB_Query_Client ----------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgGB_Query_Client( TgVOID )
{
    return (tgBF_Query_Flag_U32( &s_bfGlobal, 1 ));
}


/* ---- tgGB_Query_Server ----------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgGB_Query_Server( TgVOID )
{
    return (tgBF_Query_Flag_U32( &s_bfGlobal, 2 ));
}


/* ---- tgGB_Query_Console_HW ------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgGB_Query_Console_HW( TgVOID )
{
    return (tgBF_Query_Flag_U32( &s_bfGlobal, 3 ));
}


/* ---- tgGB_Query_Free_On_Quit ----------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgGB_Query_Free_On_Quit( TgVOID )
{
    return (tgBF_Query_Flag_U32( &s_bfGlobal, 4 ));
}


/* ---- tgGB_Parse_Command_Line ----------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgUINT32 tgGB_Parse_Command_Line( CPP_TgCHAR aszArg, C_TgSIZE uiMaxArg, PC_TgCHAR pszCmdLN )
{
    TgUINT32                            uiIndex;
    TgUINT32                            nuiCmd = 0;

    TgPARAM_CHECK(nullptr != pszCmdLN);
    TgPARAM_CHECK(nullptr != aszArg && uiMaxArg);

    /* We have a command line - parse it out. */
    tgCN_PrintF( KTgCN_CHANEL_MESSAGE | KTgCN_SEVERITY_D, TgT("Command Line: %s\n"), pszCmdLN );

    for (uiIndex = 0; 0 != pszCmdLN[uiIndex]; ++uiIndex)
    {
        /* Ignore white space command line tokens */

        if ((TgT(' ') == pszCmdLN[uiIndex]) || (TgT('\t') == pszCmdLN[uiIndex]))
        {
            pszCmdLN[uiIndex] = 0;
            continue;
        };

        if (nuiCmd + 1 >= uiMaxArg)
        {
            TgWARNING_MSGF( 0, TgT("%-16.16s(%-32.32s): Insufficient argument storage.\n"), TgT("Global"), TgT("") );
            aszArg[nuiCmd] = 0; /*« Null terminate the list of command line tokens */
            return (nuiCmd);
        }

        aszArg[nuiCmd++] = pszCmdLN + uiIndex;

        for (; (0 != pszCmdLN[uiIndex]) && (TgT(' ') != pszCmdLN[uiIndex]) && (TgT('\t') != pszCmdLN[uiIndex]); ++uiIndex)
        {
            /* Do not attempt to parse text with quotes */

            if (TgT('\"') != pszCmdLN[uiIndex])
            {
                continue;
            };

            /* Process until the end of the string or the next quotation */

            for (++uiIndex; (0 != pszCmdLN[uiIndex]) && ('\"' != pszCmdLN[uiIndex]); ++uiIndex);

            if (0 == pszCmdLN[uiIndex])
            {
                TgWARNING_MSGF( 0, TgT("%-16.16s(%-32.32s): Unbalanced quotation marks in command line.\n"), TgT("Global"), TgT("") );
                aszArg[nuiCmd] = 0; /*« Null terminate the list of command line tokens */
                return (nuiCmd);
            };
        };

        if (0 == pszCmdLN[uiIndex])
        {
            tgCN_PrintF( KTgCN_CHANEL_MESSAGE | KTgCN_SEVERITY_D, TgT("    Argument(%d) %s\n"), nuiCmd, aszArg[nuiCmd - 1] );
            aszArg[nuiCmd] = 0; /*« Null terminate the list of command line tokens */
            return (nuiCmd);
        }

        pszCmdLN[uiIndex] = 0;
        tgCN_PrintF( KTgCN_CHANEL_MESSAGE | KTgCN_SEVERITY_D, TgT("    Argument(%d) %s\n"), nuiCmd, aszArg[nuiCmd - 1] );
    };

    aszArg[nuiCmd] = 0; /*« Null terminate the list of command line tokens */
    return (nuiCmd);
}


/* ---- tgGB_Verify_Version --------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgGB_Verify_Version( C_TgUINT32 uiVersion )
{
    return (s_uiVersion == uiVersion ? TgTRUE : TgFALSE);
}