Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

f_main.cpp

Go to the documentation of this file.
00001 // OMICRON ENGINE HEADER FILE
00002 //
00003 // --------------------------------------------------------------------------
00004 // Copyright (C) 2001-2002 by Bjoern Paetzel <kolrabi@gmx.de>
00005 //
00006 // This file is part of the Omicron Engine.
00007 //
00008 // The Omicron Engine is free software; you can redistribute it and/or modify
00009 // it under the terms of the  GNU General Public License  as published by the
00010 // Free Software Foundation;  either version  2  of the License,  or (at your
00011 // option) any later version.
00012 //
00013 // The Omicron Engine  is distributed in the hope that it will be useful, but
00014 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00015 // or  FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License
00016 // for more details.
00017 //
00018 // You should have  received a copy of the  GNU General Public License  along
00019 // with The Omicron Engine;  if not,  write to the  Free Software Foundation,
00020 // Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
00021 //
00022 // --------------------------------------------------------------------------
00023 // Last modified:       $Date: 2002/12/08 20:08:15 $
00024 // By           :       $Author: kolrabi $
00025 // $Id: f_main.cpp,v 1.2 2002/12/08 20:08:15 kolrabi Exp $ 
00026 
00027 /*
00028 
00029   $Log: f_main.cpp,v $
00030   Revision 1.2  2002/12/08 20:08:15  kolrabi
00031   Now really runs under X11
00032 
00033   Revision 1.1.1.1  2002/12/07 19:02:06  kolrabi
00034   initial release
00035 
00036 
00037 */
00038  
00049 #include            <string>
00050 
00051 #include            "zlib.h"
00052 
00053 #include            "omicron/internal.h"
00054 #include            "omicron/file.h"
00055 #include            "omicron/list.h"
00056 #include            "omicron/array.h"
00057 // #include            "omicron/string.h"
00058 
00059 // never user DBGSTAMP here
00060 #undef  DBGSTAMP
00061 #define DBGSTAMP
00062 
00063 // --@@@PAK
00064 // marker for pak files attached to executable. it is interleaved because
00065 // when searching for it, it would find itself.
00066 static const char   _pak_mark1[] =          "-@@A";
00067 static const char   _pak_mark2[] =          "-@PK";
00068 static char         _pak_mark[9];
00069 static ulong        attachedpakpos = 0;
00070  
00071 /**************************************************************************** 
00072  **************************************************************************** 
00073  * VARIABLES **************************************************************** 
00074  **************************************************************************** 
00075  ****************************************************************************/ 
00076 
00077 file_manager_c::file_manager_c()
00078 {
00079     int     i;
00080 
00081     SafeDelete(gv.fileman);
00082 
00083     gv.fileman  = this;
00084     async_files = new list_c<file_t>;
00085     files       = new array_c<file_t>;
00086     pak_names   = new array_c<char>;
00087 
00088     // find marker in executable
00089     for (i=0; i<8; i++)
00090         _pak_mark[i] = i%2?_pak_mark2[i/2]:_pak_mark1[i/2];
00091 
00092     _pak_mark[i] = 0;
00093 
00094     FILE    *f = fopen(gv.init.argv[0], "rb");
00095 
00096     if (f)
00097     {
00098         ulong fit = 0;
00099         ulong p = 0;
00100         char  ch = 0;
00101 
00102         ch = fgetc(f);
00103 
00104         while(!feof(f))
00105         {
00106             if (ch==_pak_mark[fit])
00107                 fit++;
00108             else
00109                 fit = 0;
00110 
00111             if (fit == 8)
00112                 break;
00113 
00114             ch = fgetc(f);
00115             p++;
00116         }
00117 
00118         if (fit == 8)
00119             attachedpakpos = p+1;
00120         else
00121             attachedpakpos = 0;
00122 
00123         if (attachedpakpos)
00124             _log_printf(MSG_DEBUG, "attached pak found at %08x", attachedpakpos);
00125         else
00126             _log_printf(MSG_DEBUG, "attached pak not found");
00127 
00128         fclose(f);
00129     }
00130 
00131     sprintf(datadir, "data");
00132 }
00133 
00134 file_manager_c::~file_manager_c()
00135 {
00136     AssertThis;
00137 
00138     close_paks();
00139 
00140     for (slong i=0; i<files->get_count(); i++)
00141     {
00142         file_t *f = files->get(i); 
00143         if (f) close(f);
00144     }
00145 
00146     SafeDelete(files);
00147     SafeDelete(pak_names);
00148     SafeDelete(async_files); 
00149     gv.fileman = NULL;
00150 }
00151  
00152 /**************************************************************************** 
00153  **************************************************************************** 
00154  * FILE ACCESS FUNCTIONS **************************************************** 
00155  **************************************************************************** 
00156  ****************************************************************************/ 
00157  
00158 file_t *
00159 file_manager_c::load_from_disk
00160 (
00161     const char      *filename,          
00162     bool            async               
00163 )
00164 { 
00165     AssertThisV;
00166 
00167     FILE        *f;                 // the file 
00168     ulong       s;                  // for file size 
00169     file_t      *file;              // the file descriptor 
00170     std::string      szFile;
00171 
00172     szFile = datadir;
00173     szFile += "/";
00174     szFile += filename;
00175  
00176 #if defined(WIN32)
00177     int i;
00178 
00179     for (i=0; i<szFile.length(); i++)
00180       if (szFile.at(i)=='/')
00181         szFile.replace(i,1,"\\");
00182 #endif
00183  
00184     _log_printf(MSG_DEBUG, "trying to load file '%s' from disk", szFile.c_str()); 
00185  
00186     file = new file_t; 
00187     AssertReturnValue1(file, NULL);
00188  
00189     file->asyncloading  = async?1:0; 
00190     file->size          = 0;
00191     file->pos           = 0;        // set cursor to 0 
00192     file->buf           = NULL;
00193  
00194     // open file 
00195     f = fopen(szFile.c_str(), "rb"); 
00196     if (!f) 
00197     { 
00198         _log_printf(MSG_DEBUG, "file not found"); 
00199         SafeDelete(file); 
00200         return NULL; 
00201     } 
00202  
00203     // get size of file 
00204     fseek(f, 0, SEEK_END); 
00205     s = ftell(f); 
00206     fseek(f, 0, SEEK_SET); 
00207     file->size = s; 
00208  
00209     if (async) 
00210     { 
00211         file->f = f; 
00212         async_files->add_first(file); 
00213     } 
00214     else 
00215     { 
00216         // and load it 
00217         file->buf = new char[s]; 
00218         if (!file->buf) 
00219         { 
00220             fclose(f); 
00221             SafeDelete(file); 
00222             return NULL; 
00223         } 
00224         fread( file->buf, 1, (unsigned)s, f ); 
00225         fclose(f); 
00226  
00227         file->f = NULL; 
00228     } 
00229  
00230     _log_printf(MSG_NORMAL, "successfully loaded file: %s", szFile.c_str()); 
00231     file->pos = 0;                  // set cursor to 0 
00232     return file; 
00233 } // loadfromdisk 
00234  
00235 file_t *
00236 file_manager_c::load_from_pak
00237 (
00238     const char      *filename           
00239 )
00240 { 
00241     AssertThisV;
00242 
00243     file_t     *file = NULL;       // the file descriptor 
00244  
00245     std::string      szFile;
00246 
00247     szFile = filename;
00248 
00249 #if defined(WIN32)
00250     int i;
00251 
00252     for (i=0; i<szFile.length(); i++)
00253       if (szFile.at(i)=='\\')
00254         szFile.replace(i,1,"/");
00255 #endif
00256 
00257     _log_printf(MSG_DEBUG, "trying to load file '%s' from pak", szFile.c_str());
00258 
00259     for ( slong pak=0; pak<pak_names->get_count(); pak++)
00260     {
00261         char  *pname = pak_names->get(pak);
00262 
00263         if (!pname)
00264             break;
00265 
00266         FILE  *f = fopen(pname, "rb");
00267 
00268         pak_header_t h;
00269         fileentry_t  fe;
00270 
00271         fread(&h, sizeof(h), 1, f);
00272 
00273         for (ulong e = 0; e<h.entrycount; e++)
00274         {
00275             fread(&fe, sizeof(fe), 1, f);
00276             if (!strcmpi( szFile.c_str(), fe.filename )) 
00277             { 
00278                 file = create();
00279                 // save size 
00280                 file->size = fe.realsize; 
00281  
00282                 // create buffer and "load" file 
00283                 file->buf = new char[fe.realsize]; 
00284 
00285                 if (!file->buf) 
00286                 { 
00287                     SafeDelete(file); 
00288                     continue;
00289                 } 
00290 
00291                 // if realsize == size then file is uncompressed 
00292                 if (fe.size ==  
00293                     fe.realsize) 
00294                 { 
00295                     fseek(f, fe.offset, SEEK_SET);
00296                     fread(file->buf, 1, file->size, f);
00297 
00298                     fclose(f);
00299                     return file; 
00300                 } 
00301                 else // it is compressed 
00302                 { 
00303                     char *tmpbuf = new char[fe.size];
00304                     fseek(f, fe.offset, SEEK_SET);
00305                     fread(tmpbuf, 1, fe.size, f);
00306 
00307                     // file is at beginning of _pak_header + offset 
00308                     uncompress((uchar*)file->buf, 
00309                         (ulong*)&file->size, 
00310                         (uchar*)(tmpbuf), 
00311                         (ulong)fe.size); 
00312  
00313                     fclose(f);
00314                     SafeArrayDelete(tmpbuf);
00315 
00316                     _log_printf(MSG_NORMAL, 
00317                       "successfully loaded file: %s", szFile.c_str());
00318                     return file; 
00319                 } 
00320             }
00321         }
00322 
00323         fclose(f);
00324     }
00325 
00326     // try to load from attached
00327     if (attachedpakpos)
00328     {
00329         FILE  *f = fopen(gv.init.argv[0], "rb");
00330 
00331         fseek(f, attachedpakpos, SEEK_SET);
00332 
00333         pak_header_t h;
00334         fileentry_t  fe;
00335 
00336         fread(&h, sizeof(h), 1, f);
00337         for (ulong e = 0; e<h.entrycount; e++)
00338         {
00339             fread(&fe, sizeof(fe), 1, f);
00340             if (!strcmpi( szFile.c_str(), fe.filename )) 
00341             { 
00342                 file = create();
00343                 // save size 
00344                 file->size = fe.realsize; 
00345  
00346                 // create buffer and "load" file 
00347                 file->buf = new char[fe.realsize]; 
00348 
00349                 if (!file->buf) 
00350                 { 
00351                     SafeDelete(file); 
00352                     continue;
00353                 } 
00354 
00355                 // if realsize == size then file is uncompressed 
00356                 if (fe.size ==  
00357                     fe.realsize) 
00358                 { 
00359                     fseek(f, fe.offset+attachedpakpos, SEEK_SET);
00360                     fread(file->buf, 1, file->size, f);
00361 
00362                     fclose(f);
00363                     return file; 
00364                 } 
00365                 else // it is compressed 
00366                 { 
00367                     char *tmpbuf = new char[fe.size];
00368                     fseek(f, fe.offset+attachedpakpos, SEEK_SET);
00369                     fread(tmpbuf, 1, fe.size, f);
00370 
00371                     // file is at beginning of _pak_header + offset 
00372                     uncompress((uchar*)file->buf, 
00373                         (ulong*)&file->size, 
00374                         (uchar*)(tmpbuf), 
00375                         (ulong)fe.size); 
00376  
00377                     fclose(f);
00378                     SafeArrayDelete(tmpbuf);
00379 
00380                     _log_printf(MSG_NORMAL, 
00381                       "successfully loaded file: %s", szFile.c_str());
00382                     return file; 
00383                 } 
00384             }
00385         }
00386 
00387         fclose(f);
00388     }
00389  
00390     if (file) SafeDelete(file); 
00391     return NULL;                  // file will be NULL here anyway 
00392 } // loadfrompak 
00393 
00394 
00395 file_t *
00396 file_manager_c::load
00397 ( 
00398     const char      *filename,          
00399     bool            async               
00400 )
00401 {
00402     AssertThisV;
00403 
00404     file_t *f; 
00405  
00406     /* try loading from disk */
00407     f = load_from_disk( filename, async ); 
00408  
00409     if (f) return f; 
00410  
00411     /* try loading from disk */
00412     f = load_from_pak( filename ); 
00413  
00414     if (!f) 
00415         _log_printf(MSG_WARNING, "file not found: %s", filename); 
00416  
00417     return f; 
00418 } // load 
00419 
00420 ulong
00421 file_manager_c::load_pak
00422 (
00423     const char      *filename           
00424 )
00425 {
00426     AssertThisV;
00427 
00428     char *str = new char[strlen(filename)+1+strlen(datadir)+1];
00429 
00430     sprintf(str, "%s/%s", datadir, filename);
00431     _convert_file_path(str);
00432 
00433     FILE    *f = fopen(str, "rb");
00434     if (!f)
00435     {
00436         _log_printf(MSG_NORMAL, "loadpak() - file not found - '%s'", str); 
00437 
00438         SafeArrayDelete(str);
00439         return 0;
00440     }
00441     fclose(f);
00442 
00443     pak_names->add(str);
00444  
00445     return 1;
00446 } // loadpak 
00447 
00448 void
00449 file_manager_c::save 
00450 (
00451     file_t          *file,              
00452     const char      *filename           
00453 )
00454 {
00455     AssertThis;
00456 
00457     std::string fname;
00458 
00459     AssertReturn2(file, filename);
00460 
00461     fname = filename;
00462 
00463 #if defined(WIN32)
00464     int i;
00465 
00466     for (i=0; i<fname.length(); i++)
00467         if (fname.at(i)=='/')
00468             fname.replace(i,1,"\\");
00469 #endif
00470 
00471     FILE *f = fopen(fname.c_str(), "wb"); 
00472     if (!f) return; 
00473 
00474     if (file->buf) 
00475         fwrite(file->buf, 1, file->size, f); 
00476 
00477     fclose(f);
00478 } // save 
00479  
00480 void
00481 file_manager_c::resize 
00482 ( 
00483     file_t          *file,              
00484     ulong           newsize             
00485 ) 
00486 { 
00487     AssertThis;
00488 
00489     if (!file) 
00490         return; 
00491  
00492     if (!newsize) 
00493     { 
00494         SafeArrayDelete(file->buf); 
00495         file->size = file->pos = 0; 
00496         return; 
00497     } 
00498  
00499     char  *buf = new char[newsize]; 
00500     long  copysize = newsize>file->size?file->size:newsize; 
00501  
00502     memcpy(buf, file->buf, copysize); 
00503     file->size = newsize; 
00504     SafeArrayDelete(file->buf); 
00505     file->buf = buf; 
00506 } 
00507  
00508 file_t *
00509 file_manager_c::create
00510 (
00511 )
00512 {
00513     AssertThisV;
00514 
00515     file_t *f; 
00516      
00517     f = new file_t; 
00518     AssertReturnValue1(f, NULL);
00519  
00520     f->buf          = NULL; 
00521     f->pos          = 0; 
00522     f->size         = 0; 
00523     f->asyncloading = 0; 
00524  
00525     return f;
00526 } // create
00527 
00528 
00529 void
00530 file_manager_c::close
00531 (
00532     file_t          *file               
00533 )
00534 {
00535     AssertThis;
00536 
00537     AssertReturn1(file);
00538 
00539     files->remove_ptr(file);
00540     SafeArrayDelete(file->buf);
00541     SafeDelete(file);
00542 } // close
00543 
00544 ulong
00545 file_manager_c::tell
00546 (
00547     file_t          *f                  
00548 )
00549 {
00550     AssertThisV;
00551 
00552     return f->pos; 
00553 } 
00554 
00555 void
00556 file_manager_c::close_paks
00557 () 
00558 { 
00559     AssertThis;
00560 
00561     for (slong i=0; i<pak_names->get_count(); i++) 
00562     { 
00563         char *pname = pak_names->get(i);
00564         if (!pname) continue;
00565 
00566         _log_printf(MSG_DEBUG2, "closing pak file %u (%s)", i, pname); 
00567         pak_names->remove(i);
00568         SafeArrayDelete(pname);
00569     } 
00570 } // closepak 
00571  
00572 void
00573 file_manager_c::unload_pak
00574 (
00575     ulong           n                   
00576 ) 
00577 {
00578     AssertThis;
00579 
00580     char *pname = pak_names->get(n);
00581     if (!pname) return;
00582 
00583     _log_printf(MSG_DEBUG2, "closing pak file %u (%s)", n, pname); 
00584     pak_names->remove(n);
00585     SafeArrayDelete(pname);
00586 } // unloadpak 
00587  
00588 ulong
00589 file_manager_c::seek
00590 ( 
00591     file_t          *f,                 
00592     slong           offset,             
00593     ulong           origin              
00594 ) 
00595 { 
00596     AssertThisV;
00597 
00598     if (!f || !f->buf) 
00599         return 0; 
00600  
00601     switch(origin) 
00602     { 
00603         case SEEK_CUR: f->pos += (slong)offset; break; 
00604         case SEEK_END: f->pos = f->size-offset; break; 
00605         case SEEK_SET: f->pos = offset; break; 
00606         default: return 0; 
00607     } 
00608  
00609     if (f->pos<0 || f->pos>f->size || !f->buf) 
00610         return 0; 
00611  
00612     return 1; 
00613 } // seek 
00614 
00615 bool
00616 file_manager_c::eof
00617 ( 
00618     file_t          *file               
00619 ) 
00620 { 
00621     AssertThisValue(true);
00622 
00623     AssertReturnValue1(file, true);
00624 
00625     return file->pos>=file->size; 
00626 }
00627  
00628 void
00629 file_manager_c::update
00630 () 
00631 { 
00632     AssertThis;
00633 
00634     /* handle asynchronous files */
00635     if (async_files) 
00636     { 
00637         file_t *f = (file_t *)async_files->get_first(); 
00638  
00639         /* for every asynchronous file */
00640         while(f) 
00641         { 
00642             if (f->f) 
00643             { 
00644                 ulong l = 0; 
00645  
00646                 if (f->pos<f->size) 
00647                 { 
00648                     /* read a bit */
00649                     l = fread(f->buf+f->pos, 1, 1024, f->f); 
00650                     f->pos += l; 
00651                     f = (file_t *)async_files->get_next(); 
00652                 } 
00653                 else 
00654                 { 
00655                     /* if done reading, close file */
00656                     fclose(f->f); 
00657 
00658                     /* mark as loaded */
00659                     f->pos = 0; 
00660                     f->asyncloading = 0; 
00661 
00662                     /* remove from list */
00663                     async_files->remove(f); 
00664                     f = (file_t *)async_files->get_first(); 
00665                 } 
00666             } 
00667             else 
00668             { 
00669                 /* has no open file -> mark as loaded, remove */
00670                 f->pos = 0; 
00671                 f->asyncloading = 0; 
00672                 async_files->remove(f); 
00673                 f = (file_t *)async_files->get_first(); 
00674              } 
00675         } 
00676     } 
00677 } 

Generated on Wed Dec 18 15:48:46 2002 for omicron engine by doxygen1.2.18