Home

Resume

Blog

Teikitu


/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/*  »Project«   Teikitu Gaming System (TgS) (∂)
    »File«      TgS Common - Base - API - Platform.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".                                                   */
/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
#if TgCOMPILE_BASE_API_PLATFORM

MSVC_PRAGMA(warning( push, 3 ))
#include <time.h>
MSVC_PRAGMA(warning( pop ))


/* == Common ============================================================================================================================================================ */

/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  File Local Macros */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

#if TgS_STAT_COMMON
    #define STAT(...)                       __VA_ARGS__
#else
    #define STAT(...)
#endif




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

#if TgS_STAT_COMMON
static volatile TgATOMIC_SINT64             s_iStat_File_Read, s_iStat_File_Write;
#endif




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

/* ---- Time Functions -------------------------------------------------------------------------------------------------------------------------------------------------- */

static TgSINT64                     s_iInit_Start;
static TgSINT64                     s_iStart[ETgTIME_CHANNEL__COUNT - 1];
static TgFLOAT32                    s_fLast[ETgTIME_CHANNEL__COUNT - 1];
static TgFLOAT32                    s_fElapsed[ETgTIME_CHANNEL__COUNT - 1];
static TgFLOAT32                    s_fStop[ETgTIME_CHANNEL__COUNT - 1];


/* ---- timespec_get_ns ------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgSINT64 timespec_get_ns( TgVOID )
{
    timespec                            ts;

    if (0 == TgGETTIME( &ts ))
        return ts.tv_sec * 1000LL * 1000LL * 1000LL + ts.tv_nsec;
    return (0);
}


/* ---- tgTM_Init ------------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgTM_Init( TgVOID )
{
    s_iInit_Start = timespec_get_ns();
}


/* ---- tgTM_Query_Counter_Tick ----------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSINT64 tgTM_Query_Counter_Tick( TgVOID )
{
    TgSINT64                            iTime;

    iTime = timespec_get_ns();
    return (iTime - s_iInit_Start);
}


/* ---- tgTM_Counter_To_MSec -------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgFLOAT32 tgTM_Counter_Tick_To_MSec( C_TgSINT64 iTime )
{
    return ((TgFLOAT32)((TgFLOAT64)(iTime) / 1000.0 / 1000.0));
}


/* ---- tgTM_Query_Time ------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgFLOAT32 tgTM_Query_Time( TgVOID )
{
    return (tgTM_Counter_Tick_To_MSec( tgTM_Query_Counter_Tick()  ));
}


/* ---- tgTM_Channel_Query_Time ----------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgFLOAT32 tgTM_Channel_Query_Time( C_ETgTIMER_CHANNEL enChannel )
{
    TgPARAM_CHECK(enChannel < ETgTIME_CHANNEL__WALL);
    return (tgPM_FSEL_F32( -s_fStop[enChannel], tgTM_Query_Time(), s_fStop[enChannel] ));
}


/* ---- tgTM_Channel_Elapsed_Time --------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgFLOAT32 tgTM_Channel_Elapsed_Time( C_ETgTIMER_CHANNEL enChannel )
{
    TgPARAM_CHECK(enChannel < ETgTIME_CHANNEL__WALL);
    return (s_fElapsed[enChannel]);
}


/* ---- tgTM_Channel_Reset ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgTM_Channel_Reset( C_ETgTIMER_CHANNEL enChannel )
{
    TgPARAM_CHECK(enChannel < ETgTIME_CHANNEL__WALL);
    s_iStart[enChannel] = timespec_get_ns();
    s_fLast[enChannel] = tgTM_Query_Time();
    s_fElapsed[enChannel] = 0.0F;
    s_fStop[enChannel] = 0.0F;
}


/* ---- tgTM_Channel_Start ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgTM_Channel_Start( C_ETgTIMER_CHANNEL enChannel )
{
    TgPARAM_CHECK(enChannel < ETgTIME_CHANNEL__WALL);
    if (!(s_fStop[enChannel] <= 0.0F))
    {
        s_fLast[enChannel] = tgTM_Query_Time();
        s_fStop[enChannel] = 0.0F;
    };
}


/* ---- tgTM_Channel_Stop ----------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgTM_Channel_Stop( C_ETgTIMER_CHANNEL enChannel )
{
    TgPARAM_CHECK(enChannel < ETgTIME_CHANNEL__WALL);
    if (!(s_fStop[enChannel] > 0.0F))
    {
        s_fStop[enChannel] = s_fLast[enChannel];
    };
}


/* ---- tgTM_Channel_Update --------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgTM_Channel_Update( C_ETgTIMER_CHANNEL enChannel )
{
    TgPARAM_CHECK(enChannel < ETgTIME_CHANNEL__WALL);
    if (!(s_fStop[enChannel] > 0.0F))
    {
        C_TgFLOAT32 fTime = tgTM_Query_Time();
        s_fElapsed[enChannel] = tgCM_MAX_F32( KTgEPS_F32, fTime - s_fLast[enChannel] );
        s_fLast[enChannel] = fTime;
        s_fStop[enChannel] = 0.0F;
    };
}


/* ---- tgTM_Channel_Step ----------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgTM_Channel_Step( C_ETgTIMER_CHANNEL enChannel, C_TgFLOAT32 fTimeAdvance )
{
    TgPARAM_CHECK(enChannel < ETgTIME_CHANNEL__WALL);
    if (!(s_fStop[enChannel] <= 0.0F))
    {
        s_fElapsed[enChannel] = fTimeAdvance;
        s_fStop[enChannel] += fTimeAdvance;
    };
}




/* ---- IO Functions ---------------------------------------------------------------------------------------------------------------------------------------------------- */

/* ---- tgIO_File_Open -------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgIO_File_Open( P_TgSINTPTR piFile, CPC_TgCHAR pszFile, C_TgSINT32 enAccessMask )
{
    TgERROR((0 != piFile) && (0 != pszFile));

    if ((ETgFILE_IO_ACCESS__READ | ETgFILE_IO_ACCESS__WRITE) == (enAccessMask & (ETgFILE_IO_ACCESS__READ | ETgFILE_IO_ACCESS__WRITE)))
    {
        TgFOPEN( *(FILE**)piFile, pszFile, "w+" );
    }
    else  if (enAccessMask & ETgFILE_IO_ACCESS__READ)
    {
        TgFOPEN( *(FILE**)piFile, pszFile, "r+" );
    }
    else if (enAccessMask & ETgFILE_IO_ACCESS__WRITE)
    {
        TgFOPEN( *(FILE**)piFile, pszFile, "w+" );
    };

    return (nullptr != *piFile ? KTgS_OK : KTgE_FAIL);
}


/* ---- tgIO_File_Read -------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSIZE tgIO_File_Read( C_TgSINTPTR iFile, P_TgVOID pDest, TgSIZE uiTotalBytesToRead )
{
    TgSIZE                              uiTotalBytesRead;

    uiTotalBytesRead = 0;
    while (uiTotalBytesToRead > 0)
    {
        TgSIZE                              uiBytesToRead;
        TgSIZE                              uiBytesRead;

        uiBytesToRead = uiTotalBytesToRead % KTgMAX_U32;
        uiBytesRead = fread( pDest, 1, uiBytesToRead, (FILE*)iFile );
        uiTotalBytesToRead -= uiBytesRead;
        uiTotalBytesRead += uiBytesRead;
        if (uiBytesToRead != uiBytesRead)
            break;
    };

    STAT( tgAM64_XADD( &s_iStat_File_Read, (TgSINT64)uiTotalBytesRead ) );
    return (uiTotalBytesRead);
}


/* ---- tgIO_File_Write ------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSIZE tgIO_File_Write( C_TgSINTPTR iFile, CP_TgVOID pSource, TgSIZE uiTotalBytesToWrite )
{
    TgSIZE                              uiTotalBytesWriten;

    uiTotalBytesWriten = 0;
    while (uiTotalBytesToWrite > 0)
    {
        TgSIZE                              uiBytesWriten;
        TgSIZE                              uiBytesWrite;

        uiBytesWrite = uiTotalBytesToWrite % KTgMAX_U32;
        uiBytesWriten = fwrite( pSource, 1, uiBytesWrite, (FILE*)iFile );
        uiTotalBytesToWrite -= uiBytesWriten;
        uiTotalBytesWriten += uiBytesWriten;
        if (uiBytesWrite != uiBytesWriten)
            break;
        pSource = (CP_TgUINT08)pSource + uiBytesWrite;
    };

    STAT( tgAM64_XADD( &s_iStat_File_Write, (TgSINT64)uiTotalBytesWriten ) );
    return (uiTotalBytesWriten);
}


/* ---- tgIO_File_Flush ------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgIO_File_Flush( C_TgSINTPTR iFile )
{
    return (0 == fflush( (FILE*)iFile ) ? KTgS_OK : KTgE_FAIL);
}


/* ---- tgIO_File_Close ------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgIO_File_Close( C_TgSINTPTR iFile )
{
    return (0 == fclose( (FILE*)iFile ) ? KTgS_OK : KTgE_FAIL);
}


/* ---- tgIO_File_Valid ------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgIO_File_Valid( C_TgSINTPTR iFile )
{
    return (0 == iFile ? TgFALSE : TgTRUE);
}


/* ---- tgIO_File_Seek -------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgIO_File_Seek( C_TgSINTPTR iFile, C_ETgIO_SEEK enSeek_Mode, C_TgSINT64 iPos )
{
    TgBOOL                              bSuccess;

    switch (enSeek_Mode)
    {
        case ETgIO_SEEK__BEGIN:
            bSuccess = 0 == fseek( (FILE*)iFile, (long)iPos, SEEK_SET );
            break;
        case ETgIO_SEEK__END:
            bSuccess = 0 == fseek( (FILE*)iFile, (long)iPos, SEEK_END );
            break;
        case ETgIO_SEEK__CURRENT:
            bSuccess = 0 == fseek( (FILE*)iFile, (long)iPos, SEEK_CUR );
            break;

        default:
            TgS_NO_DEFAULT( return (KTgE_FAIL) );
    }

    return (bSuccess ? KTgS_OK : KTgE_FAIL);
}


/* ---- tgIO_File_Size -------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSIZE tgIO_File_Size( C_TgSINTPTR iFile )
{
    TgSINT32                            iCurrent;
    TgSINT32                            iSize;

    iCurrent = (TgSINT32)ftell( (FILE*)iFile );
    fseek( (FILE*)iFile, 0, SEEK_END );
    iSize = (TgSINT32)ftell( (FILE*)iFile );
    fseek( (FILE*)iFile, iCurrent, SEEK_SET );
    TgERROR(iSize >=0);

    return ((TgSIZE)iSize);
}


/* ---- tgIO_Directory_Make --------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgIO_Directory_Make( CPC_TgCHAR UNUSED_PARAM pszPath )
{
    return (KTgE_FAIL);
}


/* ---- tgIO_Directory_Remove ------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgIO_Directory_Remove( CPC_TgCHAR UNUSED_PARAM pszPath )
{
    return (KTgE_FAIL);
}


/* ---- tgIO_Directory_Exists ------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgIO_Directory_Exists( CPC_TgCHAR UNUSED_PARAM pszPath )
{
    return (TgFALSE);
}


/* ---- tgIO_File_Delete ------------------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgIO_File_Delete( CPC_TgCHAR pszFile )
{
    return (0 == remove( pszFile ) ? KTgS_OK : KTgE_FAIL);
}


/* ---- tgIO_File_Copy -------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgIO_File_Copy( CPC_TgCHAR pszExisting, CPC_TgCHAR pszDest )
{
    FILE                                *pSource;
    FILE                                *pDest;
    TgUINT08                            uiBuffer[1024];
    TgSIZE                              uiBytesRead;
    TgSIZE                              uiBytesWriten;

    TgFOPEN( pSource, pszExisting, "r" );
    if (!pSource)
        return (KTgE_FAIL);
    TgFOPEN( pDest, pszDest, "w" );
    if (!pDest)
        return (KTgE_FAIL);

    uiBytesRead = 0;
    uiBytesWriten = 0;

    while (!feof( pSource ))
    {
        uiBytesRead = fread( uiBuffer, 1, 1024, pSource );
        uiBytesWriten = fwrite( uiBuffer, 1, uiBytesRead, pDest );

        if (uiBytesRead != uiBytesWriten)
            break;
    };

    fclose( pDest );
    fclose( pSource );

    return (uiBytesRead != uiBytesWriten ? KTgE_FAIL : KTgS_OK);
}


/* ---- tgIO_File_Move -------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgIO_File_Move( CPC_TgCHAR pszExisting, CPC_TgCHAR pszDest )
{
    if (TgSUCCEEDED(tgIO_File_Copy( pszExisting, pszDest )))
    {
        if (TgSUCCEEDED( tgIO_File_Delete( pszExisting ) ))
        {
            return (KTgS_OK);
        }
    }
    return (KTgE_FAIL);
}


/* ---- tgIO_File_Exists ------------------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgIO_File_Exists( CPC_TgCHAR pszFile )
{
    FILE                                *pSource;

    TgFOPEN( pSource, pszFile, "r" );
    if (nullptr == pSource)
        return (TgFALSE);

    fclose( pSource );
    return (TgTRUE);
}




/* ---- DBG ERR --------------------------------------------------------------------------------------------------------------------------------------------------------- */

/* ---- tgPM_DBG_ERR_Write_Byte ----------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSIZE tgPM_DBG_ERR_Write_Byte( PC_STg2_Output UNUSED_PARAM psOut, C_TgSIZE UNUSED_PARAM uiOffset, C_TgUINT08 UNUSED_PARAM ptbUnused )
{
    return 0;
}


/* ---- tgPM_DBG_ERR_Write ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSIZE tgPM_DBG_ERR_Write( PC_STg2_Output UNUSED_PARAM psOut, C_TgSIZE UNUSED_PARAM uiOffset, CP_TgVOID pszText, C_TgSIZE _niText)
{
    printf( "%.*s", (int)(_niText / sizeof(TgCHAR)), (CP_TgCHAR)pszText );
    return 0;
}


/* ---- tgPM_DBG_OUT_Write_Byte ----------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSIZE tgPM_DBG_OUT_Write_Byte( PC_STg2_Output UNUSED_PARAM psOut, C_TgSIZE UNUSED_PARAM uiOffset, C_TgUINT08 UNUSED_PARAM ptbUnused )
{
    return 0;
}


/* ---- tgPM_DBG_OUT_Write ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSIZE tgPM_DBG_OUT_Write( PC_STg2_Output UNUSED_PARAM psOut, C_TgSIZE UNUSED_PARAM uiOffset, CP_TgVOID pszText, C_TgSIZE _niText)
{
    printf( "%.*s", (int)(_niText / sizeof(TgCHAR)), (CP_TgCHAR)pszText );
    return 0;
}


/* ---- Memory PM ------------------------------------------------------------------------------------------------------------------------------------------------------- */
CLANG_WARN_DISABLE_PUSH(missing-prototypes)

/* ---- tgMM_PM_Init_Scratch -------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
P_TgUINT08 tgMM_PM_Init_Scratch( C_TgSIZE uiSize )
{
    return ((P_TgUINT08)malloc( uiSize ));
}


/* ---- tgMM_PM_Free_Scratch -------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgMM_PM_Free_Scratch( PC_TgUINT08 pScratchMemory )
{
    free( pScratchMemory );
}


/* ---- tgMM_PM_Page_Size ----------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSINT32 tgMM_PM_Page_Size( TgVOID )
{
    return (4096);
}


/* ---- tgMM_PM_Virtual_Reserve ----------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
P_TgVOID tgMM_PM_Virtual_Reserve( C_TgSIZE iSize, C_TgBOOL UNUSED_PARAM bTemp )
{
    P_TgVOID                            pMem;
    TgSCALAR_P_ALIAS_UNION              sUnion;

    pMem = malloc( iSize + 2*(TgSIZE)tgMM_PM_Page_Size() - 1 );
    TgCRITICAL( nullptr != pMem );
    
    sUnion.m_p = pMem;
    sUnion.m_pui08 += (TgUINTPTR)tgMM_PM_Page_Size() - (sUnion.m_uiPTR % (TgUINTPTR)tgMM_PM_Page_Size());
    *sUnion.m_puiPTR = (TgUINTPTR)pMem;
    sUnion.m_pui08 += tgMM_PM_Page_Size();
    TgCRITICAL( 0 == (sUnion.m_uiPTR % (TgUINTPTR)tgMM_PM_Page_Size()) );

    return (sUnion.m_pui08);
}


/* ---- tgMM_PM_Virtual_Commit ------------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
P_TgVOID tgMM_PM_Virtual_Commit( PC_TgVOID pMem, C_TgSIZE iSize )
{
    return (nullptr == pMem ? tgMM_PM_Virtual_Reserve( iSize, TgFALSE ) : pMem);
}


/* ---- tgMM_PM_Virtual_Free -------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgMM_PM_Virtual_Free( PC_TgVOID pMem )
{
    TgSCALAR_P_ALIAS_UNION              sUnion;

    sUnion.m_p = pMem;
    sUnion.m_pui08 -= tgMM_PM_Page_Size();
  
    free( (P_TgVOID)(*sUnion.m_puiPTR)  );
}


CLANG_WARN_DISABLE_POP(missing-prototypes)
/*# TgCOMPILE_BASE_API_PLATFORM */
#endif

/* 2183: Empty Translation Unit */
CLANG_WARN_SUPPRESS(missing-prototypes)
TgVOID Prevent2183_Common_Base_API_Platform( TgVOID )
{
}