Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * OpenTyrian: A modern cross-platform port of Tyrian
  3.  * Copyright (C) 2007-2009  The OpenTyrian Development Team
  4.  *
  5.  * This program is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU General Public License
  7.  * as published by the Free Software Foundation; either version 2
  8.  * of the License, or (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  18.  */
  19. #include "file.h"
  20.  
  21. #include "opentyr.h"
  22. #include "varz.h"
  23.  
  24. #include "SDL.h"
  25.  
  26. #include <errno.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29.  
  30. const char *custom_data_dir = NULL;
  31.  
  32. // finds the Tyrian data directory
  33. const char *data_dir( void )
  34. {
  35.         const char *dirs[] =
  36.         {
  37.                 custom_data_dir,
  38.                 TYRIAN_DIR,
  39.                 "data",
  40.                 ".",
  41.         };
  42.        
  43.         static const char *dir = NULL;
  44.        
  45.         if (dir != NULL)
  46.                 return dir;
  47.        
  48.         for (uint i = 0; i < COUNTOF(dirs); ++i)
  49.         {
  50.                 if (dirs[i] == NULL)
  51.                         continue;
  52.                
  53.                 FILE *f = dir_fopen(dirs[i], "tyrian1.lvl", "rb");
  54.                 if (f)
  55.                 {
  56.                         fclose(f);
  57.                        
  58.                         dir = dirs[i];
  59.                         break;
  60.                 }
  61.         }
  62.        
  63.         if (dir == NULL) // data not found
  64.                 dir = "";
  65.        
  66.         return dir;
  67. }
  68.  
  69. // prepend directory and fopen
  70. FILE *dir_fopen( const char *dir, const char *file, const char *mode )
  71. {
  72.         char *path = malloc(strlen(dir) + 1 + strlen(file) + 1);
  73.         sprintf(path, "%s/%s", dir, file);
  74.        
  75.         FILE *f = fopen(path, mode);
  76.         fprintf(stderr, "%s\n", path);
  77.         free(path);
  78.        
  79.         return f;
  80. }
  81.  
  82. // warn when dir_fopen fails
  83. FILE *dir_fopen_warn(  const char *dir, const char *file, const char *mode )
  84. {
  85.         FILE *f = dir_fopen(dir, file, mode);
  86.        
  87.         if (f == NULL)
  88.                 fprintf(stderr, "warning: failed to open '%s': %s\n", file, strerror(errno));
  89.        
  90.         return f;
  91. }
  92.  
  93. // die when dir_fopen fails
  94. FILE *dir_fopen_die( const char *dir, const char *file, const char *mode )
  95. {
  96.         FILE *f = dir_fopen(dir, file, mode);
  97.        
  98.         if (f == NULL)
  99.         {
  100.                 fprintf(stderr, "error: failed to open '%s': %s\n", file, strerror(errno));
  101.                 fprintf(stderr, "error: One or more of the required Tyrian " TYRIAN_VERSION " data files could not be found.\n"
  102.                                 "       Please read the README file.\n");
  103.                 JE_tyrianHalt(1);
  104.         }
  105.        
  106.         return f;
  107. }
  108.  
  109. // check if file can be opened for reading
  110. bool dir_file_exists( const char *dir, const char *file )
  111. {
  112.         FILE *f = dir_fopen(dir, file, "rb");
  113.         if (f != NULL)
  114.                 fclose(f);
  115.         return (f != NULL);
  116. }
  117.  
  118. // returns end-of-file position
  119. long ftell_eof( FILE *f )
  120. {
  121.         long pos = ftell(f);
  122.        
  123.         fseek(f, 0, SEEK_END);
  124.         long size = ftell(f);
  125.        
  126.         fseek(f, pos, SEEK_SET);
  127.        
  128.         return size;
  129. }
  130.  
  131. // endian-swapping fread that dies if the expected amount cannot be read
  132. size_t efread( void *buffer, size_t size, size_t num, FILE *stream )
  133. {
  134.         size_t num_read = fread(buffer, size, num, stream);
  135.        
  136. #if SDL_BYTEORDER == SDL_BIG_ENDIAN
  137.         switch (size)
  138.         {
  139.                 case 2:
  140.                         for (size_t i = 0; i < num; i++)
  141.                                 ((Uint16 *)buffer)[i] = SDL_Swap16(((Uint16 *)buffer)[i]);
  142.                         break;
  143.                 case 4:
  144.                         for (size_t i = 0; i < num; i++)
  145.                                 ((Uint32 *)buffer)[i] = SDL_Swap32(((Uint32 *)buffer)[i]);
  146.                         break;
  147.                 case 8:
  148.                         for (size_t i = 0; i < num; i++)
  149.                                 ((Uint64 *)buffer)[i] = SDL_Swap64(((Uint64 *)buffer)[i]);
  150.                         break;
  151.                 default:
  152.                         break;
  153.         }
  154. #endif
  155.        
  156.         if (num_read != num)
  157.         {
  158.                 fprintf(stderr, "error: An unexpected problem occurred while reading from a file.\n");
  159.                 JE_tyrianHalt(1);
  160.         }
  161.  
  162.         return num_read;
  163. }
  164.  
  165. // endian-swapping fwrite that dies if the expected amount cannot be written
  166. size_t efwrite( const void *buffer, size_t size, size_t num, FILE *stream )
  167. {
  168.         void *swap_buffer = NULL;
  169.        
  170. #if SDL_BYTEORDER == SDL_BIG_ENDIAN
  171.         switch (size)
  172.         {
  173.                 case 2:
  174.                         swap_buffer = malloc(size * num);
  175.                         for (size_t i = 0; i < num; i++)
  176.                                 ((Uint16 *)swap_buffer)[i] = SDL_SwapLE16(((Uint16 *)buffer)[i]);
  177.                         buffer = swap_buffer;
  178.                         break;
  179.                 case 4:
  180.                         swap_buffer = malloc(size * num);
  181.                         for (size_t i = 0; i < num; i++)
  182.                                 ((Uint32 *)swap_buffer)[i] = SDL_SwapLE32(((Uint32 *)buffer)[i]);
  183.                         buffer = swap_buffer;
  184.                         break;
  185.                 case 8:
  186.                         swap_buffer = malloc(size * num);
  187.                         for (size_t i = 0; i < num; i++)
  188.                                 ((Uint64 *)swap_buffer)[i] = SDL_SwapLE64(((Uint64 *)buffer)[i]);
  189.                         buffer = swap_buffer;
  190.                         break;
  191.                 default:
  192.                         break;
  193.         }
  194. #endif
  195.        
  196.         size_t num_written = fwrite(buffer, size, num, stream);
  197.        
  198.         if (swap_buffer != NULL)
  199.                 free(swap_buffer);
  200.        
  201.         if (num_written != num)
  202.         {
  203.                 fprintf(stderr, "error: An unexpected problem occurred while writing to a file.\n");
  204.                 JE_tyrianHalt(1);
  205.         }
  206.        
  207.         return num_written;
  208. }
  209.