Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
  3.  * It is copyright by its individual contributors, as recorded in the
  4.  * project's Git history.  See COPYING.txt at the top level for license
  5.  * terms and a link to the Git history.
  6.  */
  7. /*
  8.  * This code provides a glue layer between PhysicsFS and Simple Directmedia
  9.  *  Layer's (SDL) RWops i/o abstraction.
  10.  *
  11.  * License: this code is public domain. I make no warranty that it is useful,
  12.  *  correct, harmless, or environmentally safe.
  13.  *
  14.  * This particular file may be used however you like, including copying it
  15.  *  verbatim into a closed-source project, exploiting it commercially, and
  16.  *  removing any trace of my name from the source (although I hope you won't
  17.  *  do that). I welcome enhancements and corrections to this file, but I do
  18.  *  not require you to send me patches if you make changes. This code has
  19.  *  NO WARRANTY.
  20.  *
  21.  * Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
  22.  *  Please see LICENSE in the root of the source tree.
  23.  *
  24.  * SDL falls under the LGPL license. You can get SDL at https://www.libsdl.org/
  25.  *
  26.  *  This file was written by Ryan C. Gordon. (icculus@clutteredmind.org).
  27.  */
  28.  
  29. #include <stdio.h>  /* used for SEEK_SET, SEEK_CUR, SEEK_END ... */
  30. #include "physfsrwops.h"
  31.  
  32. #if SDL_MAJOR_VERSION == 1
  33. #define SDL_RWops_callback_seek_position        int
  34. #define SDL_RWops_callback_read_position        int
  35. #define SDL_RWops_callback_write_position       int
  36. #else
  37. #define SDL_RWops_callback_seek_position        Sint64
  38. #define SDL_RWops_callback_read_position        size_t
  39. #define SDL_RWops_callback_write_position       size_t
  40. #endif
  41.  
  42. static SDL_RWops_callback_seek_position physfsrwops_seek(SDL_RWops *rw, const SDL_RWops_callback_seek_position offset, const int whence)
  43. {
  44.     PHYSFS_File *handle = reinterpret_cast<PHYSFS_File *>(rw->hidden.unknown.data1);
  45.     SDL_RWops_callback_seek_position pos = 0;
  46.  
  47.     if (whence == SEEK_SET)
  48.     {
  49.         pos = offset;
  50.     } /* if */
  51.  
  52.     else if (whence == SEEK_CUR)
  53.     {
  54.         PHYSFS_sint64 current = PHYSFS_tell(handle);
  55.         if (current == -1)
  56.         {
  57.             SDL_SetError("Can't find position in file: %s",
  58.                           PHYSFS_getLastError());
  59.             return(-1);
  60.         } /* if */
  61.  
  62. #if SDL_MAJOR_VERSION == 1
  63.         pos = static_cast<int>(current);
  64.         if (static_cast<PHYSFS_sint64>(pos) != current)
  65.         {
  66.             SDL_SetError("Can't fit current file position in an int!");
  67.             return(-1);
  68.         } /* if */
  69. #endif
  70.  
  71.         if (offset == 0)  /* this is a "tell" call. We're done. */
  72.             return(pos);
  73.  
  74.         pos += offset;
  75.     } /* else if */
  76.  
  77.     else if (whence == SEEK_END)
  78.     {
  79.         PHYSFS_sint64 len = PHYSFS_fileLength(handle);
  80.         if (len == -1)
  81.         {
  82.             SDL_SetError("Can't find end of file: %s", PHYSFS_getLastError());
  83.             return(-1);
  84.         } /* if */
  85.  
  86. #if SDL_MAJOR_VERSION == 1
  87.         pos = static_cast<int>(len);
  88.         if (static_cast<PHYSFS_sint64>(pos) != len)
  89.         {
  90.             SDL_SetError("Can't fit end-of-file position in an int!");
  91.             return(-1);
  92.         } /* if */
  93. #endif
  94.  
  95.         pos += offset;
  96.     } /* else if */
  97.  
  98.     else
  99.     {
  100.         SDL_SetError("Invalid 'whence' parameter.");
  101.         return(-1);
  102.     } /* else */
  103.  
  104.     if ( pos < 0 )
  105.     {
  106.         SDL_SetError("Attempt to seek past start of file.");
  107.         return(-1);
  108.     } /* if */
  109.    
  110.     if (!PHYSFS_seek(handle, static_cast<PHYSFS_uint64>(pos)))
  111.     {
  112.         SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
  113.         return(-1);
  114.     } /* if */
  115.  
  116.     return(pos);
  117. } /* physfsrwops_seek */
  118.  
  119.  
  120. static SDL_RWops_callback_read_position physfsrwops_read(SDL_RWops *const rw, void *const ptr, const SDL_RWops_callback_read_position size, const SDL_RWops_callback_read_position maxnum)
  121. {
  122.     PHYSFS_File *handle = reinterpret_cast<PHYSFS_File *>(rw->hidden.unknown.data1);
  123.     PHYSFS_sint64 rc = (PHYSFS_read)(handle, ptr, size, maxnum);
  124.     if (rc != maxnum)
  125.     {
  126.         if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
  127.             SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
  128.     } /* if */
  129.     return rc;
  130. } /* physfsrwops_read */
  131.  
  132.  
  133. static SDL_RWops_callback_write_position physfsrwops_write(SDL_RWops *const rw, const void *const ptr, const SDL_RWops_callback_write_position size, const SDL_RWops_callback_write_position num)
  134. {
  135.     PHYSFS_File *handle = reinterpret_cast<PHYSFS_File *>(rw->hidden.unknown.data1);
  136.     PHYSFS_sint64 rc = (PHYSFS_write)(handle, reinterpret_cast<const uint8_t *>(ptr), size, num);
  137.     if (rc != num)
  138.         SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
  139.     return rc;
  140. } /* physfsrwops_write */
  141.  
  142.  
  143. static int physfsrwops_close(SDL_RWops *rw)
  144. {
  145.     PHYSFS_File *handle = reinterpret_cast<PHYSFS_File *>(rw->hidden.unknown.data1);
  146.     if (!PHYSFS_close(handle))
  147.     {
  148.         SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
  149.         return(-1);
  150.     } /* if */
  151.  
  152.     SDL_FreeRW(rw);
  153.     return(0);
  154. } /* physfsrwops_close */
  155.  
  156.  
  157. static RWops_ptr create_rwops(PHYSFS_File *handle)
  158. {
  159.     if (handle == NULL)
  160.         {
  161.         SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
  162.                 return nullptr;
  163.         }
  164.     else
  165.     {
  166.                 RWops_ptr retval{SDL_AllocRW()};
  167.                 if (retval)
  168.         {
  169.             retval->seek  = physfsrwops_seek;
  170.             retval->read  = physfsrwops_read;
  171.             retval->write = physfsrwops_write;
  172.             retval->close = physfsrwops_close;
  173.             retval->hidden.unknown.data1 = handle;
  174.         } /* if */
  175.                 return retval;
  176.     } /* else */
  177. } /* create_rwops */
  178.  
  179.  
  180. RWops_ptr PHYSFSRWOPS_openRead(const char *fname)
  181. {
  182.     return(create_rwops(PHYSFS_openRead(fname)));
  183. } /* PHYSFSRWOPS_openRead */
  184.  
  185. /* end of physfsrwops.c ... */
  186.  
  187.