IFF.cc

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2000  Dancer A.L Vesperman
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #ifdef HAVE_CONFIG_H
00020 #  include <config.h>
00021 #endif
00022 
00023 
00024 #include "IFF.h"
00025 
00026 #ifndef ALPHA_LINUX_CXX
00027 #  include <cstdio>
00028 #endif
00029 #include <iostream>
00030 #include "exceptions.h"
00031 #include "utils.h"
00032 
00033 using std::string;
00034 using std::vector;
00035 
00036 #ifndef UNDER_CE
00037 using std::cout;
00038 using std::cerr;
00039 using std::endl;
00040 using std::FILE;
00041 using std::memcmp;
00042 using std::memset;
00043 using std::size_t;
00044 #endif
00045 
00046 IFF::IFF(const string &n) : U7file(n)
00047 {
00048   IndexIFFFile();
00049 }
00050 
00051 void  IFF::IndexIFFFile(void)
00052 {
00053   FILE  *fp;
00054   char  ckid[4];
00055   fp=U7open(filename.c_str(),"rb");
00056 
00057   std::fread(ckid,4,1,fp);
00058   if(memcmp(ckid,"FORM",4))
00059     throw wrong_file_type_exception(filename,"IFF");  // Not an IFF file we recognise
00060 
00061 #ifdef DEBUG
00062   cout << "Okay. It looks like an IFF file chunk" << endl;
00063 #endif
00064   long  full_length;
00065   full_length = Read4high(fp);
00066 #ifdef DEBUG
00067   cout << "length looks like: " << full_length << endl;
00068 #endif
00069   fseek(fp,4,SEEK_CUR); // We don't really need to know what the general data type is
00070 
00071 
00072 /*
00073 -the objects entries
00074   entry   = type, size, object, [even]
00075   type    = 4 chars representing the type of this object
00076   size    = reversed longint (size of the entry excluding the first 8 bytes)
00077   even    = 1 byte (set to 0) present only to get an even number of bytes
00078   (the objects found in U7 IFF files have the following format:)
00079   object  = name, data
00080   name    = 8 chars (filled with 0s)
00081   data    = the data of the object
00082 */
00083 
00084   while(ftell(fp) < full_length)
00085   {
00086     Reference r;
00087     char  type[5];
00088     memset(type,0,sizeof(type));
00089 
00090     std::fread(type,4,1,fp);  // 4 bytes of type
00091     if(type[0]<32)
00092     {
00093       // We've missed the target. Try to correct
00094       fseek(fp,-3,SEEK_CUR);
00095       continue;
00096     }
00097       
00098     r.size=Read4high(fp); // 4 bytes for len
00099     r.offset=ftell(fp);
00100     
00101     if(r.size==0||r.offset==0)
00102       break;
00103     object_list.push_back(r);
00104     fseek(fp,r.offset+r.size,SEEK_SET);
00105   }
00106 
00107   fclose(fp);
00108 }
00109 
00110 char *  IFF::retrieve(uint32 objnum, size_t &len)
00111 {
00112   FILE  *fp;
00113   char  *buffer;
00114 
00115   if (objnum >= object_list.size())
00116     throw exult_exception("objnum too large in IFF::retrieve()");
00117   
00118   fp = U7open(filename.c_str(), "rb");
00119   fseek(fp, object_list[objnum].offset, SEEK_SET);
00120   len = object_list[objnum].size;
00121   buffer = new char[len];
00122   std::fread(buffer, len, 1, fp);
00123   fclose(fp);
00124 
00125   return buffer;
00126 }
00127 

Generated on Mon Jul 9 14:42:45 2007 for ExultEngine by  doxygen 1.5.1