⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 resmgr.c

📁 空战游戏flacon源码
💻 C
📖 第 1 页 / 共 5 页
字号:
        /* The only way to insure that the heads will be in the right place is
           to reseek on every read (since multiple threads may be reading this
           file).  This is actually not as expensive as it seems.  First of all, 
           if the heads are in the same position, or the cache contains the byte
           stream from that offset, no seek will be done.  If that isn't so, a 
           seek was going to happen anyway when the OS tries to do the read. */

        lseek( file -> os_handle, (file -> seek_start + file -> current_pos), SEEK_SET );

        len = _read( file -> os_handle, buffer, count );

        if( len < 0 ) /* error, see if media has changed */
            ResCheckMedia( file -> device );
        else
            file -> current_pos += len;

        IF_LOG( LOG( "read (%s): %d\n", file -> filename, len ));
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif
        return( len );
    }
    else {

        if( count > (file -> size - file -> current_pos))
            count = file -> size - file -> current_pos;

        memcpy( buffer, file -> zip -> out_buffer + file -> current_pos, count );
        file -> current_pos += count;
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif
        return(count);
    }
    
    return( 0 );
}



/* =======================================================

   FUNCTION:   ResLoadFile

   PURPOSE:    Load an entire file into memory.  This is
               really a convenience function that 
               encorporates these components:

                  ResOpenFile
                  malloc
                  ResReadFile
                  ResCloseFile

   PARAMETERS: Filename, optional ptr to store number 
               of bytes actually read, optional ptr to 
               buffer you want file read to.

   RETURNS:    Ptr to buffer holding file or NULL (on error).

   ======================================================= */

RES_EXPORT char * ResLoadFile( const char * filename,  char * buffer, size_t * size )
{
    int file;
    int check;
    int s;
    char * alloc_buffer;

    IF_LOG( LOG( "load (%s):\n", filename ));

#if( RES_DEBUG_PARAMS )
    if( !filename ) {
        SAY_ERROR( RES_ERR_INCORRECT_PARAMETER, "ResLoadFile" );
        return( NULL );
    }
#endif /* RES_DEBUG_PARAMS */

    file = ResOpenFile( filename, _O_RDONLY | _O_BINARY );

    if( EMPTY(file))
        return( NULL ); /* message will already have been printed if using the debug version */

    s = ResSizeFile( file );

    if( !buffer ) {
		#ifdef USE_SH_POOLS
        alloc_buffer = (char *)MemAllocPtr( gResmgrMemPool, s, 0 );
		#else
        alloc_buffer = (char *)MemMalloc( s, filename );
		#endif

        if( !alloc_buffer ) {
            SAY_ERROR( RES_ERR_NO_MEMORY, filename );
            ResCloseFile( file );
            if( size )
                *size = 0;
            return( NULL );
        }
    }
    else
        alloc_buffer = buffer;

    check = ResReadFile( file, alloc_buffer, s );

    ResCloseFile( file );
   
    if( check < 0 ) /* error reading file */
    {
		#ifdef USE_SH_POOLS
        MemFreePtr( alloc_buffer );
		#else
        MemFree( alloc_buffer );
		#endif
        alloc_buffer = NULL;
    }

    if( size )
        *size = check;

    return( alloc_buffer );
}



/* =======================================================

   FUNCTION:   ResUnloadFile

   PURPOSE:    Unloads a file that was allocated via
               ResLoadFile.  This function is here for
               two purposes, 1) provide a balance to
               the API for ResLoadFile, and 2) to provide
               a placeholder should ResLoadFile be expanded
               to allow some sort of caching.

   PARAMETERS: Memory pointer that was returned from
               ResLoadFile.

   RETURNS:    None.

   ======================================================= */

RES_EXPORT void ResUnloadFile( char * buffer )
{

#if( RES_DEBUG_PARAMS )
   if( !buffer ) {
      SAY_ERROR( RES_ERR_INCORRECT_PARAMETER, "ResUnloadFile" );
      return;
   }
#endif /* RES_DEBUG_PARAMS */

	#ifdef USE_SH_POOLS
    MemFreePtr( buffer );
	#else
    MemFree( buffer );
	#endif
}



/* =======================================================

   FUNCTION:   ResCloseFile

   PURPOSE:    Close a previously opened file.

   PARAMETERS: File int.

   RETURNS:    TRUE (pass) / FALSE (fail)

   ======================================================= */

RES_EXPORT int ResCloseFile( int file )
{
    HASH_ENTRY * entry;
    char         filename[_MAX_PATH],
                 dirpath[_MAX_PATH];
    long         size;
    int          retval = 1;


#if( RES_DEBUG_PARAMS )
    if( file < 0 || file >= MAX_FILE_HANDLES ) {
        SAY_ERROR( RES_ERR_INCORRECT_PARAMETER, "ResCloseFile" );
        return( FALSE );
    }

    if( FILE_HANDLES[ file ].os_handle == -1 ) {
        SAY_ERROR( RES_ERR_ILLEGAL_FILE_HANDLE, "ResCloseFile" );
        return( FALSE );
    }
#endif /* RES_DEBUG_PARAMS */

#if (RES_MULTITHREAD)
	REQUEST_LOCK(GLOCK);
#endif

    IF_LOG( LOG( "close (%s):\n", FILE_HANDLES[ file ].filename ));

    SHOULD_I_CALL_WITH( CALLBACK_CLOSE_FILE, file, retval );

    if( !FILE_HANDLES[file].zip ) {
        /* if the file has been written to, recheck the size */

        if( FILE_HANDLES[file].csize == (unsigned int)WRITTEN_TO_FLAG ) {
            /* flush to disk */
            _commit( FILE_HANDLES[file].os_handle );

            /* go to the end of the file */
            size = lseek( FILE_HANDLES[file].os_handle, 0, SEEK_END );

            split_path( FILE_HANDLES[file].filename, filename, dirpath );

#if( !RES_USE_FLAT_MODEL )
            entry = hash_find( dirpath, GLOBAL_HASH_TABLE );
            
            if( entry ) {
                entry = hash_find( filename, (HASH_TABLE *)entry -> dir );
                if( entry )
                    entry -> size = size;
                else {
                    SAY_ERROR( RES_ERR_UNKNOWN, "set size" );
                }
            }
            else {
                SAY_ERROR( RES_ERR_UNKNOWN, "set size" );
            }
#else /* flat model */

            entry = hash_find( filename, GLOBAL_HASH_TABLE );

            if( entry )
                entry -> size = size;
            else {
                SAY_ERROR( RES_ERR_UNKNOWN, "set size" );
            }
#endif /* !RES_USE_FLAT_MODEL */
        }

        if( !FILE_HANDLES[ file ].seek_start )  /* don't close an archive */
            _close( FILE_HANDLES[ file ].os_handle );

		#ifdef USE_SH_POOLS
        MemFreePtr( FILE_HANDLES[ file ].filename );
		#else
        MemFree( FILE_HANDLES[ file ].filename );
		#endif
        FILE_HANDLES[ file ].filename = NULL;
        FILE_HANDLES[ file ].os_handle = -1;
#if (RES_MULTITHREAD)
	RELEASE_LOCK(GLOCK);
#endif

        return( TRUE );
    }
    else
    {
		#ifdef USE_SH_POOLS
        MemFreePtr( FILE_HANDLES[file].zip );
        MemFreePtr( FILE_HANDLES[file].filename );
		#else
        MemFree( FILE_HANDLES[file].zip );
        MemFree( FILE_HANDLES[file].filename );
		#endif
        FILE_HANDLES[ file ].zip = NULL;
        FILE_HANDLES[ file ].filename = NULL;
        FILE_HANDLES[ file ].os_handle = -1;
#if (RES_MULTITHREAD)
	RELEASE_LOCK(GLOCK);
#endif

        return( TRUE );
    }
#if (RES_MULTITHREAD)
	RELEASE_LOCK(GLOCK);
#endif

    return( FALSE );
}



/* =======================================================

   FUNCTION:   ResWriteFile

   PURPOSE:    Write to a file via the Resource Manager.

   PARAMETERS: File int, ptr to a buffer to get
               data from, number of bytes to write.

   RETURNS:    Number of bytes actually written.

   ======================================================= */

RES_EXPORT size_t ResWriteFile( int handle, const void * buffer, size_t count )
{
    FILE_ENTRY * file;
    int check;
    int retval = 1;

#if( RES_DEBUG_PARAMS )
    if( handle < 0 || handle >= MAX_FILE_HANDLES || !buffer ) {
        SAY_ERROR( RES_ERR_INCORRECT_PARAMETER, "ResWriteFile" );
        return( 0 );
    }
#endif /* RES_DEBUG_PARAMS */
#if (RES_MULTITHREAD)
	REQUEST_LOCK(GLOCK);
#endif

    file = &FILE_HANDLES[ handle ];

    if( file -> os_handle == -1 ) {
        SAY_ERROR( RES_ERR_ILLEGAL_FILE_HANDLE, "ResWriteFile" );
#if (RES_MULTITHREAD)
	RELEASE_LOCK(GLOCK);
#endif

        return(0);
    }
   
    if( !(file -> mode & (_O_CREAT | _O_APPEND | _O_RDWR | _O_WRONLY))) {
        SAY_ERROR( RES_ERR_PROBLEM_WRITING, file -> filename );
#if (RES_MULTITHREAD)
	RELEASE_LOCK(GLOCK);
#endif
        return(0);
    }

    SHOULD_I_CALL_WITH( CALLBACK_WRITE_FILE, handle, retval );

    /* Set a bit so we know to reestablish the file size on ResCloseFile()        */
    /* Use the csize field since we no this is not used for files we can write to */

    file -> csize = (unsigned int)WRITTEN_TO_FLAG;

    IF_LOG( LOG( "write (%s): (%d bytes)\n", file -> filename, count ));

    check = _write( file -> os_handle, buffer, count );

    if( check < 0 )
        ResCheckMedia( file -> device );
    else
        file -> current_pos += count;
#if (RES_MULTITHREAD)
	RELEASE_LOCK(GLOCK);
#endif

    return( check );
}



/* =======================================================

   FUNCTION:   ResDeleteFile

   PURPOSE:    Remove a file from the r/w medium.

   PARAMETERS: Filename.

   RETURNS:    TRUE (pass) / FALSE (fail)

   ======================================================= */

RES_EXPORT int ResDeleteFile( const char * name )
{
    HASH_ENTRY * entry;
    HASH_TABLE * table;

    int check;

#if( RES_DEBUG_PARAMS )
    if( !name ) {
        SAY_ERROR( RES_ERR_INCORRECT_PARAMETER, "ResDeleteFile" );
        return( FALSE );
    }
#endif
#if (RES_MULTITHREAD)
	REQUEST_LOCK(GLOCK);
#endif

    IF_LOG( LOG( "delete: %s\n", name ));

#if( !RES_USE_FLAT_MODEL )
    /* find both the entry & the table it resides in */
    entry = hash_find_table( name, &table );
#else
    entry = hash_find( name, GLOBAL_HASH_TABLE );

    table = GLOBAL_HASH_TABLE;
#endif

    if( !entry ) {
        SAY_ERROR( RES_ERR_FILE_NOT_FOUND, name );
#if (RES_MULTITHREAD)
	RELEASE_LOCK(GLOCK);
#endif
        return( FALSE );
    }

    if( entry -> file_position == -1 ) {
        chmod( entry -> name, _S_IWRITE );
        check = remove( entry -> name );

        if( check == -1 ) {
            SAY_ERROR( RES_ERR_CANT_DELETE_FILE, name );
        }

        /* don't return yet, remove file from hash 
           table even if delete at os level fails */
    }

#if (RES_MULTITHREAD)
	RELEASE_LOCK(GLOCK);
#endif
    return( hash_delete( entry, table ));
}



/* =============================================

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -