home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.68.zip / src / bme / bme_io.c < prev    next >
C/C++ Source or Header  |  2008-07-13  |  8KB  |  354 lines

  1. //
  2. // BME (Blasphemous Multimedia Engine) datafile IO main module
  3. //
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <ctype.h>
  9. #include <SDL/SDL.h>
  10.  
  11. #include "bme_main.h"
  12. #include "bme_err.h"
  13. #include "bme_cfg.h"
  14.  
  15. typedef struct
  16. {
  17.     Uint32 offset;
  18.     Sint32 length;
  19.     char name[13];
  20. } HEADER;
  21.  
  22. typedef struct
  23. {
  24.     HEADER *currentheader;
  25.     int filepos;
  26.     int open;
  27. } HANDLE;
  28.  
  29. static int io_usedatafile = 0;
  30. static HEADER *fileheaders;
  31. static unsigned files;
  32. static char ident[4];
  33. static char *idstring = "DAT!";
  34. static HANDLE handle[MAX_HANDLES];
  35. static FILE *fileptr[MAX_HANDLES] = {NULL};
  36. static FILE *datafilehandle = NULL;
  37. static unsigned char *datafileptr;
  38. static unsigned char *datafilestart;
  39.  
  40. static unsigned freadle32(FILE *index);
  41. static void linkedseek(unsigned pos);
  42. static void linkedread(void *buffer, int length);
  43. static unsigned linkedreadle32(void);
  44.  
  45. void io_setfilemode(int usedf)
  46. {
  47.     io_usedatafile = usedf;
  48. }
  49.  
  50. int io_openlinkeddatafile(unsigned char *ptr)
  51. {
  52.     int index;
  53.  
  54.     if (datafilehandle) fclose(datafilehandle);
  55.     datafilehandle = NULL;
  56.  
  57.     datafilestart = ptr;
  58.     linkedseek(0);
  59.  
  60.     linkedread(ident, 4);
  61.     if (memcmp(ident, idstring, 4))
  62.     {
  63.         bme_error = BME_WRONG_FORMAT;
  64.         return BME_ERROR;
  65.     }
  66.  
  67.     files = linkedreadle32();
  68.     fileheaders = malloc(files * sizeof(HEADER));
  69.     if (!fileheaders)
  70.     {
  71.         bme_error = BME_OUT_OF_MEMORY;
  72.         return BME_ERROR;
  73.     }
  74.     for (index = 0; index < files; index++)
  75.     {
  76.         fileheaders[index].offset = linkedreadle32();
  77.         fileheaders[index].length = linkedreadle32();
  78.         linkedread(&fileheaders[index].name, 13);
  79.     }
  80.  
  81.     for (index = 0; index < MAX_HANDLES; index++) handle[index].open = 0;
  82.     io_usedatafile = 1;
  83.     bme_error = BME_OK;
  84.     return BME_OK;
  85. }
  86.  
  87. int io_opendatafile(char *name)
  88. {
  89.     int index;
  90.  
  91.     if (name)
  92.     {
  93.         datafilehandle = fopen(name, "rb");
  94.         if (!datafilehandle)
  95.         {
  96.             bme_error = BME_OPEN_ERROR;
  97.             return BME_ERROR;
  98.         }
  99.     }
  100.  
  101.     fread(ident, 4, 1, datafilehandle);
  102.     if (memcmp(ident, idstring, 4))
  103.     {
  104.         bme_error = BME_WRONG_FORMAT;
  105.         return BME_ERROR;
  106.     }
  107.  
  108.     files = freadle32(datafilehandle);
  109.     fileheaders = malloc(files * sizeof(HEADER));
  110.     if (!fileheaders)
  111.     {
  112.         bme_error = BME_OUT_OF_MEMORY;
  113.         return BME_ERROR;
  114.     }
  115.     for (index = 0; index < files; index++)
  116.     {
  117.         fileheaders[index].offset = freadle32(datafilehandle);
  118.         fileheaders[index].length = freadle32(datafilehandle);
  119.         fread(&fileheaders[index].name, 13, 1, datafilehandle);
  120.     }
  121.  
  122.     for (index = 0; index < MAX_HANDLES; index++) handle[index].open = 0;
  123.     io_usedatafile = 1;
  124.     bme_error = BME_OK;
  125.     return BME_OK;
  126. }
  127.  
  128. // Returns nonnegative file handle if successful, -1 on error
  129.  
  130. int io_open(char *name)
  131. {
  132.     if (!name) return -1;
  133.  
  134.     if (!io_usedatafile)
  135.     {
  136.         int index;
  137.         for (index = 0; index < MAX_HANDLES; index++)
  138.         {
  139.             if (!fileptr[index]) break;
  140.         }
  141.         if (index == MAX_HANDLES) return -1;
  142.         else
  143.         {
  144.             FILE *file = fopen(name, "rb");
  145.             if (!file)
  146.             {
  147.                 return -1;
  148.             }
  149.             else
  150.             {
  151.                 fileptr[index] = file;
  152.                 return index;
  153.             }
  154.         }
  155.     }
  156.     else
  157.     {
  158.         int index;
  159.         int namelength;
  160.         char namecopy[13];
  161.  
  162.         namelength = strlen(name);
  163.         if (namelength > 12) namelength = 12;
  164.         memcpy(namecopy, name, namelength + 1);
  165.         for (index = 0; index < strlen(namecopy); index++)
  166.         {
  167.             namecopy[index] = toupper(namecopy[index]);
  168.         }
  169.  
  170.         for (index = 0; index < MAX_HANDLES; index++)
  171.         {
  172.             if (!handle[index].open)
  173.             {
  174.                 int count = files;
  175.                 handle[index].currentheader = fileheaders;
  176.  
  177.                 while (count)
  178.                 {
  179.                     if (!strcmp(namecopy, handle[index].currentheader->name))
  180.                     {
  181.                          handle[index].open = 1;
  182.                          handle[index].filepos = 0;
  183.                          return index;
  184.                     }
  185.                     count--;
  186.                     handle[index].currentheader++;
  187.                 }
  188.                 return -1;
  189.             }
  190.         }
  191.         return -1;
  192.     }
  193. }
  194.  
  195. // Returns file position after seek or -1 on error
  196.  
  197. int io_lseek(int index, int offset, int whence)
  198. {
  199.     if (!io_usedatafile)
  200.     {
  201.          fseek(fileptr[index], offset, whence);
  202.          return ftell(fileptr[index]);
  203.     }
  204.     else
  205.     {
  206.         int newpos;
  207.  
  208.         if ((index < 0) || (index >= MAX_HANDLES)) return -1;
  209.  
  210.         if (!handle[index].open) return -1;
  211.         switch(whence)
  212.         {
  213.             default:
  214.             case SEEK_SET:
  215.             newpos = offset;
  216.             break;
  217.  
  218.             case SEEK_CUR:
  219.             newpos = offset + handle[index].filepos;
  220.             break;
  221.  
  222.             case SEEK_END:
  223.             newpos = offset + handle[index].currentheader->length;
  224.             break;
  225.         }
  226.         if (newpos < 0) newpos = 0;
  227.         if (newpos > handle[index].currentheader->length) newpos = handle[index].currentheader->length;
  228.         handle[index].filepos = newpos;
  229.         return newpos;
  230.     }
  231. }
  232.  
  233. // Returns number of bytes actually read, -1 on error
  234.  
  235. int io_read(int index, void *buffer, int length)
  236. {
  237.     if (!io_usedatafile)
  238.     {
  239.         return fread(buffer, 1, length, fileptr[index]);
  240.     }
  241.     else
  242.     {
  243.         int readbytes;
  244.  
  245.         if ((index < 0) || (index >= MAX_HANDLES)) return -1;
  246.  
  247.         if (!handle[index].open) return -1;
  248.         if (length + handle[index].filepos > handle[index].currentheader->length)
  249.         length = handle[index].currentheader->length - handle[index].filepos;
  250.         
  251.         if (datafilehandle)
  252.         {
  253.             fseek(datafilehandle, handle[index].currentheader->offset + handle[index].filepos, SEEK_SET);
  254.             readbytes = fread(buffer, 1, length, datafilehandle);
  255.         }
  256.         else
  257.         {
  258.             linkedseek(handle[index].currentheader->offset + handle[index].filepos);
  259.             linkedread(buffer, length);
  260.             readbytes = length;
  261.         }
  262.         handle[index].filepos += readbytes;
  263.         return readbytes;
  264.     }
  265. }
  266.  
  267. // Returns nothing
  268.  
  269. void io_close(int index)
  270. {
  271.     if (!io_usedatafile)
  272.     {
  273.         fclose(fileptr[index]);
  274.         fileptr[index] = NULL;
  275.     }
  276.     else
  277.     {
  278.         if ((index < 0) || (index >= MAX_HANDLES)) return;
  279.  
  280.         handle[index].open = 0;
  281.     }
  282. }
  283.  
  284. unsigned io_read8(int index)
  285. {
  286.     unsigned char byte;
  287.  
  288.     io_read(index, &byte, 1);
  289.     return byte;
  290. }
  291.  
  292. unsigned io_readle16(int index)
  293. {
  294.     unsigned char bytes[2];
  295.  
  296.     io_read(index, bytes, 2);
  297.     return (bytes[1] << 8) | bytes[0];
  298. }
  299.  
  300. unsigned io_readhe16(int index)
  301. {
  302.     unsigned char bytes[2];
  303.  
  304.     io_read(index, bytes, 2);
  305.     return (bytes[0] << 8) | bytes[1];
  306. }
  307.  
  308. unsigned io_readle32(int index)
  309. {
  310.     unsigned char bytes[4];
  311.  
  312.     io_read(index, bytes, 4);
  313.     return (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
  314. }
  315.  
  316. unsigned io_readhe32(int index)
  317. {
  318.     unsigned char bytes[4];
  319.  
  320.     io_read(index, bytes, 4);
  321.     return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
  322. }
  323.  
  324. static unsigned freadle32(FILE *file)
  325. {
  326.     unsigned char bytes[4];
  327.  
  328.     fread(&bytes, 4, 1, file);
  329.     return (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
  330. }
  331.  
  332. static void linkedseek(unsigned pos)
  333. {
  334.     datafileptr = &datafilestart[pos];
  335. }
  336.  
  337. static void linkedread(void *buffer, int length)
  338. {
  339.     unsigned char *dest = (unsigned char *)buffer;
  340.     while (length--)
  341.     {
  342.         *dest++ = *datafileptr++;
  343.     }
  344. }
  345.  
  346. static unsigned linkedreadle32(void)
  347. {
  348.     unsigned char bytes[4];
  349.  
  350.     linkedread(&bytes, 4);
  351.     return (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
  352. }    
  353.  
  354.