예제 #1
0
void TheGameLoop()
{
	// If the game is not inited then do it now.
	if(!bGameInited && FileCheckSum())
	{
		if(tSettings.bPlayOnline)
		{			
			pNetGame = new CNetGame(tSettings.szConnectHost,atoi(tSettings.szConnectPort),
				tSettings.szNickName,tSettings.szConnectPass);
		}

		pGame->ToggleFrameLimiterState(TRUE);
		bGameInited = TRUE;

		return;
	}

	// The NetGame processing has been moved
	// to the Direct3DDevice::Present hook.
	// This is to solve alt-tab issues.

   // BEGIN: HEALTH BAR AND PLAYER NAME STUFF 
    if(!pGame->IsMenuActive() && bShowNameTags) {

      if(!bbfont) 
      { 
         bbfont = new CBBFont(pD3DDevice, "vcmpfnt"); 
         bbfont->Initialise(); 
      } 

      if (!HealthBarOldStateBlock) 
      { 
         pD3DDevice->BeginStateBlock(); 
         pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); 
         pD3DDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); 
         pD3DDevice->SetRenderState(D3DRS_ZENABLE, 1); 
         pD3DDevice->SetRenderState(D3DRS_FILLMODE, 3); 
         pD3DDevice->SetRenderState(D3DRS_CULLMODE, 1); 
         pD3DDevice->SetRenderState(D3DRS_WRAP0, 0); 
         pD3DDevice->SetRenderState(D3DRS_CLIPPING, 1); 
         pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, 0); 
         pD3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 1); 
         pD3DDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, 0); 
         pD3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 15); 
         pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 1); 
         pD3DDevice->SetRenderState(D3DRS_SRCBLEND, 5); 
         pD3DDevice->SetRenderState(D3DRS_DESTBLEND, 6); 
         pD3DDevice->SetRenderState(D3DRS_BLENDOP, 1); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, 4); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, 2); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, 0); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, 4); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, 2); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, 0); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, 0); 
         pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, 1); 
         pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, 1); 
         pD3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); 
         pD3DDevice->SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE); 
         pD3DDevice->SetStreamSource(0, NULL, 0); 
         pD3DDevice->EndStateBlock(&HealthBarOldStateBlock); 
      } 

      if (!HealthBarNewStateBlock) 
      { 
         pD3DDevice->BeginStateBlock(); 
         pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); 
         pD3DDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); 
         pD3DDevice->SetRenderState(D3DRS_ZENABLE, 1); 
         pD3DDevice->SetRenderState(D3DRS_FILLMODE, 3); 
         pD3DDevice->SetRenderState(D3DRS_CULLMODE, 1); 
         pD3DDevice->SetRenderState(D3DRS_WRAP0, 0); 
         pD3DDevice->SetRenderState(D3DRS_CLIPPING, 1); 
         pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, 0); 
         pD3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 1); 
         pD3DDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, 0); 
         pD3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 15); 
         pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 1); 
         pD3DDevice->SetRenderState(D3DRS_SRCBLEND, 5); 
         pD3DDevice->SetRenderState(D3DRS_DESTBLEND, 6); 
         pD3DDevice->SetRenderState(D3DRS_BLENDOP, 1); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, 4); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, 2); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, 0); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, 1); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, 2); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, 0); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); 
         pD3DDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, 0); 
         pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, 1); 
         pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, 1); 
         pD3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); 
         pD3DDevice->SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE); 
         pD3DDevice->EndStateBlock(&HealthBarNewStateBlock); 
      } 

      pD3DDevice->CaptureStateBlock(HealthBarOldStateBlock); 
      pD3DDevice->ApplyStateBlock(HealthBarNewStateBlock); 

      D3DXMATRIX matTransposed; 
      D3DXMatrixTranspose(&matTransposed, (D3DXMATRIX*)&matView); 
      matTransposed._14 = matTransposed._24 = matTransposed._34 = 0.0f; 

      if(pNetGame) 
      { 
         CPlayerPool* pPlayerPool = pNetGame->GetPlayerPool(); 
         for(int x=0; x < MAX_PLAYERS; x++) 
         { 
            if(pPlayerPool->GetSlotState(x) == TRUE) // player is in use 
            { 
               CRemotePlayer* Player = pPlayerPool->GetAt(x); 

               if( Player->IsActive() && 
                  (Player->GetDistanceFromLocalPlayer() <= 80.0f) ) // Active and within reasonable distance 
               { 
                  CPlayerPed* PlayerPed = Player->GetPlayerPed(); 
                   
                  if(PlayerPed->IsOnScreen()) 
                  { // They're onscreen 
                     MATRIX4X4 matPlayer; 
                     PlayerPed->GetMatrix(&matPlayer); 
                     matTransposed._41 = matPlayer.vPos.X; 
                     matTransposed._42 = matPlayer.vPos.Y; 
                     matTransposed._43 = matPlayer.vPos.Z + 1.0f; 
                     pD3DDevice->SetTransform(D3DTS_WORLD, &matTransposed); 

                     float Health = Player->GetReportedHealth(); 
                     if (Health > 100.0f) Health = 100.0f; 

                     HealthBarBGVertices[0].x = HealthBarBGVertices[1].x = (0.0058f * Health) - 0.29f; 
                     pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, HealthBarBDRVertices, sizeof(HealthBarVertices_s)); 
                     pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, HealthBarVertices,    sizeof(HealthBarVertices_s)); 
                     pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, HealthBarBGVertices,  sizeof(HealthBarVertices_s)); 
                      
                     if(bbfont) { 
                        bbfont->Begin(); 
                        //bbfont->Draw(pPlayerPool->GetPlayerName(x), 0.285f, 0xFF000000);
						bbfont->Draw(pPlayerPool->GetPlayerName(x), 0.300f, Player->GetTeamColorAsARGB()); 
                        bbfont->End(); 
                     } 
                  } 
               } 
            } 
         } 
      } 

	  pD3DDevice->ApplyStateBlock(HealthBarOldStateBlock); 
	  // END:   HEALTH BAR AND PLAYER NAME STUFF 
	}

	if(!pGame->IsMenuActive())
	{
		if((pNetGame) && GetAsyncKeyState(VK_F5)) {
			pGame->DisplayHud(FALSE);
			pScoreBoard->Draw();
		}
		else if((pNetGame) && GetAsyncKeyState(VK_F6)) {
			pGame->DisplayHud(FALSE);
			pNetStats->Draw();
		} 
		else
		{
			pGame->DisplayHud(TRUE);
			if(pChatWindow) pChatWindow->Draw();
			if(pCmdWindow) pCmdWindow->Draw();
		}
	}
}
예제 #2
0
/*-------------------------------------------------------------------
    Procedure   :       Load .Trg File
    Input       :       char    *   Filename
    Output      :       BOOL    TRUE/FALSE
-------------------------------------------------------------------*/
BOOL Triggerload( char * Filename )
{
    long            File_Size;
    long            Read_Size;
    char        *   Buffer;
    char        *   OrgBuffer;
    int         *   intpnt;
    uint8       *   byteptr;
    float       *   floatptr;
    int         i, j, k;
    TRIGGERVAR  *   v;
    TRIGGER     *   t;
    TRIGGERMOD  *   m;
    EVENT       *   e;
    CONDITION   *   c;
    uint32          MagicNumber;
    uint32          VersionNumber;
    uint32      *   uint32Pnt;
    TRIGGERVAR  *   TVpnt;


    NumOfTrigVars = 0;
    NumOfTriggers = 0;
    NumOfTrigMods = 0;
    NumOfTrigModQues = 0;
    NumOfEvents = 0;
    NumOfConditions = 0;
    Level_End = NULL;
    AvatarActivated = NULL;
    DecreaseTemperature = NULL;
    MinimumTemperature = NULL;
    TimeLimitTrigger = NULL;

    FileCheckSum( Filename );

    File_Size = Get_File_Size( Filename );  
//  if( !File_Size ) return FALSE;
    if( !File_Size ) return TRUE;

    Buffer = malloc( File_Size );

    if( Buffer == NULL )
        return FALSE;
    OrgBuffer = Buffer;

    Read_Size = Read_File( Filename, Buffer, File_Size );

    if( Read_Size != File_Size )
        return FALSE;

    uint32Pnt = (uint32 *) Buffer;
    MagicNumber = *uint32Pnt++;
    VersionNumber = *uint32Pnt++;
    Buffer = (char *) uint32Pnt;

    if( ( MagicNumber != MAGIC_NUMBER ) || ( VersionNumber != TRG_VERSION_NUMBER  ) )
    {
        Msg( "TriggerLoad() Incompatible triggers( .TRG ) file %s", Filename );
        return( FALSE );
    }

    intpnt = (int *) Buffer;

    if ( TrigVars )
    {
        for ( i = 0; i < NumOfTrigVars; i++ )
        {
            if ( TrigVars[ i ].Triggers )
                free( TrigVars[ i ].Triggers );
        }
        free( TrigVars );
    }
    TrigVars = NULL;

    if ( Triggers )
    {
        for ( i = 0; i < NumOfTriggers; i++ )
        {
            if ( Triggers[ i ].Conditions )
                free( Triggers[ i ].Conditions );
        }
        free( Triggers );
    }
    Triggers = NULL;

    if ( Events )
    {
        free( Events );
    }
    Events = NULL;

    if ( Conditions )
    {
        for ( i = 0; i < NumOfConditions; i++ )
        {
            if ( Conditions[ i ].Triggers )
                free( Conditions[ i ].Triggers );
            if ( Conditions[ i ].Events )
                free( Conditions[ i].Events );
        }
        free( Conditions );
    }
    Conditions = NULL;

    if ( TrigModQue )
    {
        free( TrigModQue );
    }
    TrigModQue = NULL;

    for ( i = 0; i < MAX_PLAYERS; i++ )
    {
        if ( init_shortcopy && ShortTriggerCopy[ i ] )
            free( ShortTriggerCopy[ i ] );
        ShortTriggerCopy[ i ] = NULL;
        if ( init_shortcopy && ShortTrigVarCopy[ i ] )
            free( ShortTrigVarCopy[ i ] );
        ShortTrigVarCopy[ i ] = NULL;
    }
    init_shortcopy = 1;

    if ( ActiveConditions )
    {
        free( ActiveConditions );
    }
    ActiveConditions = NULL;

    NumOfTrigVars = *intpnt++;
    NumOfTriggers = *intpnt++;
    NumOfTrigMods = *intpnt++;
    NumOfTrigModQues = NumOfTrigMods * 2; // bodge it and scarper...
    NumOfEvents = *intpnt++;
    NumOfConditions = *intpnt++;
    NumOfActiveConditions = 0;

    if ( NumOfTrigVars )
    {
        TrigVars = (TRIGGERVAR *) calloc( NumOfTrigVars, sizeof( TRIGGERVAR ) );
        if ( !TrigVars )
        {
            Msg( "TriggerLoad() malloc failed for %d triggervars", NumOfTrigVars );
            return FALSE;
        }
        for ( i = 0; i < MAX_PLAYERS; i++ )
        {
            ShortTrigVarCopy[ i ] = (SHORTTRIGVAR *) calloc( NumOfTrigVars, sizeof( SHORTTRIGVAR ) );
            if ( !ShortTrigVarCopy[ i ] )
            {
                Msg( "TriggerLoad() malloc failed for %d short triggervars for player %d of %d",
                    NumOfTrigVars, i, MAX_PLAYERS );
                return FALSE;
            }
        }
    }

    if ( NumOfTriggers )
    {
        Triggers = (TRIGGER *) calloc( NumOfTriggers, sizeof( TRIGGER ) );
        if ( !Triggers )
        {
            Msg( "TriggerLoad() malloc failed for %d triggers", NumOfTriggers );
            return FALSE;
        }
        for ( i = 0; i < MAX_PLAYERS; i++ )
        {
            ShortTriggerCopy[ i ] = (SHORTTRIGGER *) calloc( NumOfTriggers, sizeof( SHORTTRIGGER ) );
            if ( !ShortTriggerCopy[ i ] )
            {
                Msg( "TriggerLoad() malloc failed for %d short triggers for player %d of %d",
                    NumOfTriggers, i, MAX_PLAYERS );
                return FALSE;
            }
        }
    }

    if ( NumOfTrigMods )
    {
        TrigMods = (TRIGGERMOD *) calloc( NumOfTrigMods, sizeof( TRIGGERMOD ) );
        if ( !TrigMods )
        {
            Msg( "TriggerLoad() malloc failed for %d triggermods", NumOfTrigMods );
            return FALSE;
        }
        TrigModQue = (TRIGGERMODQUE *) calloc( NumOfTrigModQues, sizeof( TRIGGERMODQUE ) );
        if ( !TrigModQue )
        {
            Msg( "TriggerLoad() malloc failed for %d triggermodques", NumOfTrigModQues );
            return FALSE;
        }
        for( i = 0 ; i < NumOfTrigModQues ; i++ )
        {
            TrigModQue[i].Time = 0.0F;
        }
    }

    if ( NumOfEvents )
    {
        Events = (EVENT *) calloc( NumOfEvents, sizeof( EVENT ) );
        if ( !Events )
        {
            Msg( "TriggerLoad() malloc failed for %d events", NumOfEvents );
            return FALSE;
        }
    }

    if ( NumOfConditions )
    {
        Conditions = (CONDITION *) calloc( NumOfConditions, sizeof( CONDITION ) );
        if ( !Conditions )
        {
            Msg( "TriggerLoad() malloc failed for %d conditions", NumOfConditions );
            return FALSE;
        }
        ActiveConditions = (CONDITION **) calloc( NumOfConditions, sizeof( CONDITION ) );
        if ( !ActiveConditions )
        {
            Msg( "TriggerLoad() malloc failed for %d active conditions", NumOfConditions );
            return FALSE;
        }
    }


    for ( i = 0; i < NumOfTrigVars; i++ )
    {
        v = &TrigVars[ i ];
        byteptr = (uint8 *) intpnt;
        for ( j = 0; j < sizeof( v->Name ); j++ )
        {
            v->Name[ j ] = *byteptr++;
        }
        intpnt = (int *) byteptr;
        v->InitState = *intpnt++;
        v->State = v->InitState;
        v->NumOfTriggers = *intpnt++;
        if ( v->NumOfTriggers )
        {
            v->Triggers = (TRIGGER **) calloc( v->NumOfTriggers, sizeof( TRIGGER * ) );
            if ( !v->Triggers )
            {
                Msg( "TriggerLoad() malloc failed for %d triggers in trigvar %d of %d",
                    v->NumOfTriggers, i, NumOfTrigVars );
                return FALSE;
            }
        }
        else
            v->Triggers = NULL;
        for ( j = 0; j < v->NumOfTriggers; j++ )
        {
            k = *intpnt++;
            if ( k >= NumOfTriggers )
                return FALSE;
            v->Triggers[ j ] = &Triggers[ k ];
        }
    }

    for ( i = 0; i < NumOfTriggers; i++ )
    {
        t = &Triggers[ i ];
        byteptr = (uint8 *) intpnt;
        t->Type = *byteptr++;
        intpnt = (int *) byteptr;
        j = *intpnt++;
        if ( j >= NumOfTrigVars )
            return FALSE;
        t->TrigVar = &TrigVars[ j ];
        t->ActiveState = *intpnt++;
        t->Active = 0;
        t->NumOfConditions = *intpnt++;
        if ( t->NumOfConditions )
        {
            t->Conditions = (CONDITION **) calloc( t->NumOfConditions, sizeof( CONDITION * ) );
            if ( !t->Conditions )
            {
                Msg( "TriggerLoad() malloc failed for %d conditions in trigger %d of %d\n",
                    t->NumOfConditions, i, NumOfTriggers );
                return FALSE;
            }
        }
        else
            t->Conditions = NULL;
        for ( j = 0; j < t->NumOfConditions; j++ )
        {
            k = *intpnt++;
            if ( k >= NumOfConditions )
                return FALSE;
            t->Conditions[ j ] = &Conditions[ k ];
        }
    }

    for ( i = 0; i < NumOfTrigMods; i++ )
    {
        m = &TrigMods[ i ];
        m->Op = *intpnt++;
        j = *intpnt++;
        if ( j >= NumOfTrigVars )
            return FALSE;
        m->TrigVar = &TrigVars[ j ];
        m->Val = *intpnt++;

        floatptr = (float*) intpnt;
        m->Time = *floatptr++ * 60.0F;
        intpnt = (int*) floatptr;
                
        j = *intpnt++;
        if ( j >= NumOfTrigMods )
            return FALSE;
        m->Next = ( j < 0 ) ? NULL : &TrigMods[ j ];

    }

    byteptr = (uint8 *) intpnt;
    for ( i = 0; i < NumOfEvents; i++ )
    {
        e = &Events[ i ];
        e->Type = *byteptr++;
        for ( j = 0; j < MAXDATAPEREVENT; j++ )
        {
            e->Data[ j ] = *byteptr++;
        }
    }

    intpnt = (int *) byteptr;
    for ( i = 0; i < NumOfConditions; i++ )
    {
        c = &Conditions[ i ];
        c->NumOfTriggers = *intpnt++;
        if ( c->NumOfTriggers )
        {
            c->Triggers =  (TRIGGER **) calloc( c->NumOfTriggers, sizeof( TRIGGER * ) );
            if ( !c->Triggers )
            {
                Msg( "TriggerLoad() malloc failed for %d triggers in condition %d of %d",
                    c->NumOfTriggers, i, NumOfConditions );
                return FALSE;
            }
        }
        else
            c->Triggers = NULL;
        for ( j = 0; j < c->NumOfTriggers; j++ )
        {
            k = *intpnt++;
            if ( k >= NumOfTriggers )
                return FALSE;
            c->Triggers[ j ] = &Triggers[ k ];
        }
        c->NumOfEvents = *intpnt++;
        if ( c->NumOfEvents )
        {
            c->Events = (EVENT **) calloc( c->NumOfEvents, sizeof( EVENT * ) );
            if ( !c->Events )
            {
                Msg( "TriggerLoad() malloc failed for %d events in condition %d of %d",
                    c->NumOfEvents, i, NumOfConditions );
                return FALSE;
            }
        }
        else
            c->Events = NULL;
        for ( j = 0; j < c->NumOfEvents; j++ )
        {
            k = *intpnt++;
            if ( k > NumOfEvents )
                return FALSE;
            c->Events[ j ] = &Events[ k ];
        }
    }

    TVpnt = TrigVars;
    if( TVpnt )
    {
        for( i = 0 ; i < NumOfTrigVars ; i ++ )
        {
            if( !(_strnicmp( "LEVEL_END" , &TVpnt->Name[0], 9 ) ) )
            {
                Level_End = TVpnt;
                break;
            }
            TVpnt++;
        }
    }
    if( ChangeLevel_MyGameStatus == STATUS_PostStartingSinglePlayer || ChangeLevel_MyGameStatus == STATUS_SinglePlayer || ( ChangeLevel_MyGameStatus == STATUS_TitleLoadGamePostStartingSinglePlayer) )

    {
        if( !Level_End)
        {
            Msg( "TriggerLoad() Couldnt find a Level_end var");
        }
    }

    // Search for the Avatar boss Activation    
    TVpnt = TrigVars;
    if( TVpnt )
    {
        for( i = 0 ; i < NumOfTrigVars ; i ++ )
        {
            if( !(_strnicmp( "AvatarActivated" , &TVpnt->Name[0], 15 ) ) )
            {
                AvatarActivated = TVpnt;
                break;
            }
            TVpnt++;
        }
    }

/*-------------------------------------------------------------------
    Search for Temperature Variable
-------------------------------------------------------------------*/
    TVpnt = TrigVars;
    if( TVpnt )
    {
        for( i = 0 ; i < NumOfTrigVars ; i ++ )
        {
            if( !(_strnicmp( "Decreasetemperature" , &TVpnt->Name[0], 19 ) ) )
            {
                DecreaseTemperature = TVpnt;
                break;
            }
            TVpnt++;
        }

        TVpnt = TrigVars;
        for( i = 0 ; i < NumOfTrigVars ; i ++ )
        {
            if( !(_strnicmp( "Minimumtemperature" , &TVpnt->Name[0], 18 ) ) )
            {
                MinimumTemperature = TVpnt;
                break;
            }
            TVpnt++;
        }
    }
/*-------------------------------------------------------------------
    Search for Temperature Variable
-------------------------------------------------------------------*/
    TVpnt = TrigVars;
    if( TVpnt )
    {
        for( i = 0 ; i < NumOfTrigVars ; i ++ )
        {
            if( !(_strnicmp( "Timelimit" , &TVpnt->Name[0], 9 ) ) )
            {
                TimeLimitTrigger = TVpnt;
                break;
            }
            TVpnt++;
        }
    }
/*-----------------------------------------------------------------*/

    for( i = 0 ; i < NumOfTrigModQues ; i++ )
    {
        TrigModQue[i].Time = 0.0F;
    }
    NumOfActiveConditions = 0;
    
    free( OrgBuffer );
    return TRUE;
}
예제 #3
0
/*-------------------------------------------------------------------
    Procedure   :   Load Texture Pages, Offsets and Sizes
                :   for 2D Faceme polygons
    Input       :   int8        *   Filename of offset file
                :   BOOL            Scale
                :   BOOL            LoadTPages
    Output      :   FRAME_INFO  *   Structure for offset file
-------------------------------------------------------------------*/
FRAME_INFO * Load_Off_File( int8 * Filename, BOOL Scale, int LoadTPages, int16 *last_tpage, int16 xsize, int16 ysize, BOOL placeholder )
{
    int16           Name_Index[ MAX_NAMES ];
    int8        *   Off_Buffer;
    uint32          File_Size;
    uint32          Read_Size;
    int8        *   Char_Ptr;
    int16       *   Short_Ptr;
    BOX_INFO    *   Box_Info;
    int16           Num_Boxes;
    BIT_INFO    *   Bit_Info;
    int16           Num_Frames;
    OFF_INFO    *   Off_Info;
    int16           Num_Offs;
    FRAME_INFO  *   Frm_Info = NULL;
    int16           Num_TPages;
    int16           Count;
    char            tpagename[32];
    int8            TempFilename[ 256 ];
    OFF_BUFFER      *Placeholder_Off_Buffer;
    
    Frm_Info = malloc( sizeof( FRAME_INFO ) );                          // Allocate memory for return structure
    if( Frm_Info == NULL ) return( NULL );

    if( placeholder )
    {
        Placeholder_Off_Buffer = (OFF_BUFFER *)malloc( sizeof( OFF_BUFFER ) );                                  // Allocate memory 
        if( Placeholder_Off_Buffer == NULL )
        {
            free( Frm_Info );
            return( NULL );
        }

        Frm_Info->vid_tpage_index = AddTexture( &Tloadheader, "", TRUE , Scale , FALSE, xsize, ysize ); // add dummy texture
        if( Frm_Info->vid_tpage_index == -1 )
        {
            free( Frm_Info );
            free( Placeholder_Off_Buffer );
            return ( NULL );
        }

        Frm_Info->tpage_name[ 0 ] = 0;
        Frm_Info->sys_tpage_index = -1;

        Box_Info = &Placeholder_Off_Buffer->box_info;
        Off_Info = &Placeholder_Off_Buffer->off_info;
        Bit_Info = &Placeholder_Off_Buffer->bit_info;

        Box_Info->tpage = Frm_Info->vid_tpage_index; 
        Box_Info->u1 = 0.0F;
        Box_Info->v1 = 0.0F;
        Box_Info->u2 = 1.0F;
        Box_Info->v2 = 1.0F;
        Box_Info->xsize = xsize;
        Box_Info->ysize = ysize;

        Off_Info->xoff = 0;
        Off_Info->yoff = 0;
        Off_Info->box = 0;

        Bit_Info->startbit = 0;
        Bit_Info->numbits = 1;

        Frm_Info->Num_Frames = 1;
        Frm_Info->File_Addr = ( int8 *)Placeholder_Off_Buffer;
        Frm_Info->Box_Info = Box_Info;
        Frm_Info->Off_Info = Off_Info;
        Frm_Info->Bit_Info = Bit_Info;
        Frm_Info->NumBoxes = 1;

    }
    else
    {
        FileCheckSum( Filename );

        File_Size = Get_File_Size( Filename );                              // Get size of file to load
        if( File_Size == 0 )
        {
            free( Frm_Info );
            return( NULL );
        }
                                                                            
        Off_Buffer = malloc( File_Size );                                   // Allocate memory to load file into
        if( Off_Buffer == NULL )
        {
            free( Frm_Info );
            return( NULL );
        }
                                                                            
        Read_Size = Read_File( Filename, Off_Buffer, File_Size );           // Read file
        if( Read_Size != File_Size )
        {
            free( Frm_Info );
            free( Off_Buffer );
            return( NULL );
        }
                                                                            
        Short_Ptr = (int16 *) Off_Buffer;                                   
                                                                            
        Num_TPages = *Short_Ptr++;                                          // Number of possible new texture pages

        Char_Ptr = (int8 *) Short_Ptr;

        for( Count = 0; Count < Num_TPages; Count++ )
        {
            sprintf( &TempFilename[ 0 ], "textures\\%s", Char_Ptr );

            if( LoadTPages & LOAD_TPAGES_VIDMEM)
            {
                Name_Index[ Count ] = AddTexture( &Tloadheader, &TempFilename[ 0 ], TRUE , Scale , FALSE, 0, 0 );
                strcpy ( tpagename, Char_Ptr );
                *last_tpage = Name_Index[ Count ];
                if( Name_Index[ Count ] == -1 )
                {
                    free( Frm_Info );
                    free( Off_Buffer );
                    return( NULL );
                }
            }

            if ( LoadTPages & LOAD_TPAGES_SYSMEM )
                strcpy (SystemMemTPages[ CurrentSysTexture ].FileName, &TempFilename[ 0 ] );    // store name of tpage

            Char_Ptr += ( strlen( Char_Ptr ) + 1 );
        }

        // copy t-page info into Frm_Info - this is only valid if only one t-page is used!
        strcpy ( Frm_Info->tpage_name, tpagename );
        Frm_Info->vid_tpage_index = Name_Index[ 0 ];

        if ( LoadTPages & LOAD_TPAGES_SYSMEM )
        {
            Frm_Info->sys_tpage_index = CurrentSysTexture;
            SystemMemTPages[ CurrentSysTexture ].VidTPageIndex = Name_Index[ 0 ];
            SystemMemTPages[ CurrentSysTexture ].lpSrcTextureSurf = NULL;
            CurrentSysTexture++;

            if (CurrentSysTexture == MAXSYSTEMMEMTPAGES)
            {
                Msg("2dTextures.c: Load_Off_File() Max system mem t-pages exceeded\n");
                exit(1);
            }
        }else
        {
            Frm_Info->sys_tpage_index = -1;
        }

        Short_Ptr = (int16 *) Char_Ptr;
        Num_Boxes = *Short_Ptr++;                                           // Number of Boxes
        Box_Info = (BOX_INFO *) Short_Ptr;

        Short_Ptr = (int16 *) ( Box_Info + Num_Boxes );
        Num_Frames = *Short_Ptr++;                                          // Number of Frames
        Bit_Info = (BIT_INFO *) Short_Ptr;

        Short_Ptr = (int16 *) ( Bit_Info + Num_Frames );
        Num_Offs = *Short_Ptr++;                                            // Number of Offsets
        Off_Info = (OFF_INFO *) Short_Ptr;

        for( Count = 0; Count < Num_Boxes; Count++ )
        {
            if ((LoadTPages & LOAD_TPAGES_SYSMEM) && (!(LoadTPages & LOAD_TPAGES_VIDMEM)))
                    Box_Info[ Count ].tpage = *last_tpage;

            if (LoadTPages & LOAD_TPAGES_VIDMEM)
                Box_Info[ Count ].tpage = Name_Index[ Box_Info[ Count ].tpage ];    // Update TPages
        }

        Frm_Info->Num_Frames = Num_Frames;
        Frm_Info->File_Addr = Off_Buffer;
        Frm_Info->Box_Info = Box_Info;
        Frm_Info->Off_Info = Off_Info;
        Frm_Info->Bit_Info = Bit_Info;
        Frm_Info->NumBoxes = Num_Boxes;
    }

    return( Frm_Info );
}