Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

sgstream.cpp

Go to the documentation of this file.
00001 
00008 /*
00009     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00010     Copyright (C) 1994-2005  Martin Bickel  and  Marc Schellenberger
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; see the file COPYING. If not, write to the
00024     Free Software Foundation, Inc., 59 Temple Place, Suite 330,
00025     Boston, MA  02111-1307  USA
00026 */
00027 
00028 
00029 
00030 #include <cstdlib>
00031 #include <cstring>
00032 #include <stdlib.h>
00033 #include <stdio.h>
00034 #include <math.h>
00035 #include <stdarg.h>
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038 #include <fstream>
00039 #include <boost/regex.hpp>
00040 
00041 #include "global.h"
00042 #include "typen.h"
00043 #include "basegfx.h"
00044 #include "misc.h"
00045 #include "sgstream.h"
00046 #include "basestrm.h"
00047 #include "palette.h"
00048 #include "gameoptions.h"
00049 
00050 #ifdef _WIN32_
00051  #include <windows.h>
00052  #include <winreg.h>
00053  #include <shlobj.h>
00054 #endif 
00055 
00056 
00057 const char* asc_EnvironmentName = "ASC_CONFIGFILE";
00058 int dataVersion = 0;
00059 
00060 const int object_version = 1;
00061 const int technology_version = 1;
00062 
00063 
00064 
00065 
00066 void loadpalette ( void )
00067 {
00068    if ( ! asc_paletteloaded ) {
00069       displayLogMessage ( 4, "loading palette ... " );
00070 
00071       tnfilestream stream ("palette.pal", tnstream::reading);
00072       stream.readdata( & pal, sizeof(pal));
00073       colormixbufchar = new char [ sizeof ( tmixbuf ) ];
00074       colormixbuf = (pmixbuf) colormixbufchar;
00075       stream.readdata( colormixbuf,  sizeof ( *colormixbuf ));
00076 
00077       for ( int i= 0; i < 8; i++ ) {
00078          stream.readdata( &xlattables.xl[i], sizeof ( xlattables.a.dark05 ));
00079          xlattables.xl[i][255] = 255;
00080       }
00081 /*
00082       stream.readdata( &xlattables.a.dark1,  sizeof ( xlattables.a.dark1 ));
00083       xlattables.a.dark1[255] = 255;
00084 
00085       stream.readdata( &xlattables.a.dark2,  sizeof ( xlattables.a.dark2 ));
00086       xlattables.a.dark2[255] = 255;
00087 
00088       stream.readdata( &xlattables.a.dark3,  sizeof ( xlattables.a.dark3 ));
00089       xlattables.a.dark3[255] = 255;
00090 
00091       stream.readdata( &xlattables.light,  sizeof ( xlattables.light ));
00092       xlattables.light[255] = 255;
00093   */
00094 #ifdef use_truecolor2pal
00095       stream.readdata( &truecolor2pal_table,  sizeof ( truecolor2pal_table ));
00096       stream.readdata( &bi2asc_color_translation_table,  sizeof ( bi2asc_color_translation_table ));
00097 #endif
00098       xlatpictgraytable = (ppixelxlattable) asc_malloc( sizeof(*xlatpictgraytable) );
00099       // xlatpictgraytable = new tpixelxlattable;
00100       generategrayxlattable(xlatpictgraytable,160,16,&pal);
00101 
00102       (*xlatpictgraytable)[255] = 255;
00103 
00104       asc_paletteloaded = 1;
00105       displayLogMessage ( 4, "done\n" );
00106    }
00107 
00108 }
00109 
00110 
00111 
00112 ASCString resolvePath( ASCString path )
00113 {
00114 #ifdef WIN32
00115    static boost::regex exevar( "\\$\\(?EXEPATH\\)?", boost::regex::icase);
00116    path = boost::regex_replace( path, exevar, ConfigurationFileLocator::Instance().getExecutableLocation(), boost::regex_constants::format_literal );
00117 
00118    static boost::regex appdata( "\\$\\(?APPDATA\\)?", boost::regex::icase);
00119    path = boost::regex_replace( path, appdata, ConfigurationFileLocator::Instance().getSpecialPath( CSIDL_APPDATA ), boost::regex_constants::format_literal );
00120 
00121    static boost::regex commonappdata( "\\$\\(?COMMON_APPDATA\\)?", boost::regex::icase);
00122    path = boost::regex_replace( path, commonappdata, ConfigurationFileLocator::Instance().getSpecialPath( CSIDL_COMMON_APPDATA ), boost::regex_constants::format_literal );
00123 
00124    static boost::regex myDocs( "\\$\\(?MY_DOCUMENTS\\)?", boost::regex::icase);
00125    path = boost::regex_replace( path, myDocs, ConfigurationFileLocator::Instance().getSpecialPath( CSIDL_PERSONAL ), boost::regex_constants::format_literal );
00126 #endif
00127 
00128    /*
00129    boost::smatch what;
00130    if ( boost::regex_match(path, what, exevar )) 
00131       return boost::regex_match( ConfigurationFileLocator::Instance().getExecutableLocation() + "\\";
00132 
00133    static boost::regex appdata( "\\$\\(?APPDATA\\)?", boost::regex::icase);
00134    if ( boost::regex_match(path, what, appdata )) 
00135       return ConfigurationFileLocator::Instance().getSpecialPath( CSIDL_APPDATA ) + "\\";
00136 
00137    static boost::regex commonappdata( "\\$\\(?COMMIN_APPDATA\\)?", boost::regex::icase);
00138    if ( boost::regex_match(path, what, commonappdata )) 
00139       return ConfigurationFileLocator::Instance().getSpecialPath( CSIDL_COMMON_APPDATA ) + "\\" ;
00140 */
00141    return path;
00142 }
00143 
00144 
00145 bool makeDirectory ( const ASCString& path )
00146 {
00147    if ( path.empty() )
00148       return false;
00149       
00150    ASCString path2 = resolvePath( path );
00151 
00152    char tmp[10000];
00153    constructFileName( tmp, 0, path2.c_str(), NULL );
00154 
00155    int existence = directoryExist ( tmp );
00156 
00157    if ( !existence ) {
00158       int res = createDirectory( tmp ); 
00159       if ( res ) {
00160          fprintf(stderr, "could neither access nor create directory %s\n", tmp );
00161          return false;
00162       }
00163    }
00164 
00165    return true;
00166 }
00167 
00168 
00169 ASCString getDirectory( ASCString filename )
00170 {
00171    if ( directoryExist( filename ))
00172       return filename;
00173 
00174    ASCString directory;
00175 
00176    static boost::regex dir( "(.*)[\\\\/:][^\\\\/:]+");
00177    boost::smatch what;
00178    if( boost::regex_match( filename, what, dir)) {
00179       directory.assign( what[1].first, what[1].second );
00180       return directory;
00181    } else
00182       return ".";
00183 }
00184 
00185 
00186 void ConfigurationFileLocatorCore::setCommandLineParam( const ASCString& path )
00187 {
00188    cmdline = path;
00189 }
00190 
00191 void ConfigurationFileLocatorCore::setExecutableLocation( const ASCString& path )
00192 {
00193    exePath = getDirectory( path );
00194 }
00195 
00196 
00197 ASCString ConfigurationFileLocatorCore::getExecutableLocation()
00198 {
00199    return exePath;
00200 }
00201 
00202 
00203 ASCString ConfigurationFileLocatorCore::getSpecialPath( int type)
00204 {
00205 #ifdef WIN32
00206    TCHAR szPath[MAX_PATH];
00207 
00208    if ( SUCCEEDED(SHGetFolderPath( NULL, type, NULL, SHGFP_TYPE_CURRENT, szPath ))) {
00209       ASCString dir = szPath;
00210       appendbackslash ( dir );
00211       dir += "ASC";
00212       appendbackslash ( dir );
00213       return dir;
00214    } 
00215 
00216 #endif
00217    return "";
00218 }
00219 
00220 vector<ASCString> ConfigurationFileLocatorCore::getDefaultDirectory()
00221 {
00222    vector<ASCString> dirs;
00223 
00224 #ifdef _WIN32_
00225    HKEY key;
00226    if (  RegOpenKeyEx ( HKEY_LOCAL_MACHINE,
00227                            "SOFTWARE\\Advanced Strategic Command\\",
00228                            0,
00229                            KEY_READ,
00230                            &key ) == ERROR_SUCCESS) {
00231 
00232       DWORD type;
00233       const int size = 2000;
00234       char  buf[size];
00235       DWORD size2 = size;
00236       if ( RegQueryValueEx ( key, "InstallDir2", NULL, &type, (BYTE*)buf, &size2 ) == ERROR_SUCCESS ) {
00237          if ( type == REG_SZ     ) {
00238             ASCString dir = buf;
00239             appendbackslash ( dir );
00240             dirs.push_back( dir );
00241          }
00242       }
00243 
00244       RegCloseKey ( key );
00245    }
00246 
00247 /*
00248    ASCString dir = getSpecialPath( CSIDL_APPDATA );
00249    if ( !dir.empty() )
00250       dirs.push_back(dir);
00251 
00252    dir = getSpecialPath( CSIDL_COMMON_APPDATA );
00253    if ( !dir.empty() )
00254       dirs.push_back(dir);
00255       */
00256 
00257 
00258    dirs.push_back( "$(MY_DOCUMENTS)\\" );
00259    dirs.push_back( "$(APPDATA)\\" );
00260    dirs.push_back( "$(COMMON_APPDATA)\\" );
00261    dirs.push_back( "$(EXEPATH)\\" );
00262    /*
00263    if ( !exePath.empty()) 
00264       dirs.push_back( exePath );
00265       */
00266 
00267 
00268 #else
00269    ASCString dir = getenv("HOME");
00270    appendbackslash ( dir );
00271    dir += ".asc/";
00272    dirs.push_back( dir );
00273 #endif
00274 
00275    return dirs;
00276 
00277 }
00278 
00279 
00280 
00281 
00282 ASCString ConfigurationFileLocatorCore::getConfigFileName()
00283 {
00284    if ( cmdline.length() ) {
00285       configFileType = 1;
00286       displayLogMessage( 7, "ConfigurationFileLocatorCore::getConfigFileName() returns cmdline: " + cmdline + "\n" );
00287       return cmdline;      
00288    }
00289 
00290    if ( getenv ( asc_EnvironmentName )) {
00291       ASCString res = getenv ( asc_EnvironmentName );
00292       configFileType = 2;
00293       displayLogMessage( 7, "ConfigurationFileLocatorCore::getConfigFileName() returns env dir: " + res + "\n" );
00294       return res;
00295    }
00296 
00297    if ( !exePath.empty() && !isPathRelative(exePath) ) {
00298       displayLogMessage( 5, "Exe path is " + exePath + "\n" );
00299       ASCString completeName = exePath + "/" + asc_configurationfile;
00300       if ( exist( completeName )) {
00301          configFileType = 3;
00302          displayLogMessage( 7, "ConfigurationFileLocatorCore::getConfigFileName() returns exepath: " + completeName + "\n" );
00303          return completeName;
00304       }
00305    }
00306 
00307    vector<ASCString> list = getDefaultDirectory();
00308    if ( list.size() >= 1 ) {
00309       configFileType = 4;
00310       for ( vector<ASCString>::iterator i = list.begin(); i != list.end(); ++i ) {
00311          ASCString p = resolvePath( *i ) + asc_configurationfile; 
00312          if( exist( p )) {
00313             displayLogMessage( 7, "ConfigurationFileLocatorCore::getConfigFileName() returns default dir: " + p + "\n" );
00314             return p;
00315          }
00316       }
00317       ASCString res = resolvePath( list[0] ) + asc_configurationfile;
00318       displayLogMessage( 7, "ConfigurationFileLocatorCore::getConfigFileName() returns list0: " + res + "\n" );
00319       return res;
00320    }
00321 
00322    configFileType = 5;
00323    displayLogMessage( 7, "ConfigurationFileLocatorCore::getConfigFileName() returns asc_configurationfile: " + ASCString(asc_configurationfile) + "\n" );
00324    return asc_configurationfile;
00325 
00326 }
00327 
00328 ASCString ConfigurationFileLocatorCore::getConfigForPrinting()
00329 {
00330    return "";
00331 }
00332 
00333 ConfigurationFileLocatorCore::ConfigurationFileLocatorCore() : configFileType(-1) 
00334 {
00335 }
00336 
00337 void ConfigurationFileLocatorCore::writeDefaultPathsToOptions()
00338 {
00339    #ifdef WIN32
00340    vector<ASCString> dirs = getDefaultDirectory();
00341    CGameOptions::Instance()->searchPathNum = 0;
00342    for ( vector<ASCString>::iterator i = dirs.begin(); i != dirs.end(); ++i )
00343       CGameOptions::Instance()->addSearchPath ( *i );
00344    #else
00345    CGameOptions::Instance()->setDefaultDirectories();
00346    #endif
00347 }
00348 
00349 ASCString getConfigFileName ()
00350 {
00351    ASCString configFileName = ConfigurationFileLocator::Instance().getConfigFileName();
00352    if ( !configFileName.empty() )
00353       return configFileName ;
00354    else
00355       return "-none- ; default values used";
00356 }
00357 
00358 
00359 
00360 int readgameoptions ( const ASCString& filename )
00361 {
00362    displayLogMessage ( 4, "loading game options ... " );
00363 
00364 
00365    displayLogMessage ( 6, ASCString("Path is ") + filename + "; " );
00366 
00367 
00368    if ( exist ( filename )) {
00369       displayLogMessage ( 6, "found, " );
00370       try {
00371          CGameOptions::Instance()->load( filename );
00372       } 
00373       catch ( ParsingError err ) {
00374          fatalError ( "Error parsing text file " + err.getMessage() );
00375       }
00376       catch ( tfileerror err ) {
00377          fatalError ( "Error loading file " + err.getFileName() );
00378       }
00379       catch ( ... ) {
00380          fatalError ( "caught undefined exception" );
00381       }
00382 
00383    } else {
00384      displayLogMessage ( 6, "not found, using defaults, " );
00385 
00386      ConfigurationFileLocator::Instance().writeDefaultPathsToOptions();
00387 
00388      if ( !filename.empty() ) {
00389         CGameOptions::Instance()->setChanged();
00390         if ( writegameoptions( filename ))
00391            displayLogMessage ( 6, "A config file has been sucessfully written to " + filename + " ");
00392         else
00393            displayLogMessage ( 6, "Failed to write config file to " + filename + " ");
00394      }
00395    }
00396 
00397    displayLogMessage ( 4, "done\n" );
00398 
00399    makeDirectory ( CGameOptions::Instance()->getSearchPath(0) );
00400 
00401    return 0;
00402 }
00403 
00404 bool writegameoptions ( ASCString configFileName )
00405 {
00406    try {
00407       if ( configFileName.empty() )
00408          configFileName = ConfigurationFileLocator::Instance().getConfigFileName();
00409 
00410       configFileName = resolvePath( configFileName );
00411 
00412       if ( CGameOptions::Instance()->isChanged() && !configFileName.empty() ) {
00413          char buf[10000];
00414          if ( makeDirectory ( extractPath ( buf, configFileName.c_str() ))) {
00415             CGameOptions::Instance()->save( configFileName );
00416             return true;
00417          }
00418       }
00419    }
00420    catch ( ... ) {
00421       // warning("Could not save game options");
00422    }
00423    return false;
00424 }
00425 
00426 void checkFileLoadability ( const ASCString& filename )
00427 {
00428    try {
00429       tnfilestream strm ( filename, tnstream::reading );
00430       strm.readChar();
00431    }
00432    catch ( ASCexception ) {
00433       ASCString msg = "Unable to access " + filename + "\n";
00434       msg +=           "Make sure the file main.ascdat is in one of the search paths specified in your config file !\n";
00435 
00436       ASCString configFileName = ConfigurationFileLocator::Instance().getConfigFileName();
00437       if ( exist( configFileName ))
00438          msg +=        "The configuration file that is used is: " + configFileName  + "\n";
00439       else
00440          if ( !configFileName.empty() ) {
00441             CGameOptions::Instance()->setChanged();
00442             if ( writegameoptions( configFileName ))
00443                msg += "A configuration file has been written to " + configFileName + "\n";
00444          }
00445 
00446       msg +=           "These paths are being searched for data files:\n ";
00447       
00448       for ( int i = 0; i < getSearchPathNum(); ++i )
00449          if ( !getSearchPath(i).empty() ) 
00450             msg += getSearchPath(i) + "\n ";
00451 
00452      fatalError ( msg );
00453    }
00454    catch ( ... ) {
00455       fatalError ( "checkFileLoadability threw an unspecified exception\n" );
00456    }
00457 }
00458 
00459 
00460 
00461 void initFileIO ( const ASCString& configFileName, int skipChecks )
00462 {
00463 
00464    ConfigurationFileLocator::Instance().setCommandLineParam( configFileName );
00465    
00466    readgameoptions( ConfigurationFileLocator::Instance().getConfigFileName() );
00467 
00468    for ( int i = 0; i < CGameOptions::Instance()->getSearchPathNum(); i++ )
00469       if ( !CGameOptions::Instance()->getSearchPath(i).empty()   ) {
00470          displayLogMessage ( 3, "adding search patch " + CGameOptions::Instance()->getSearchPath(i) + "\n" );
00471          ASCString path = resolvePath( CGameOptions::Instance()->getSearchPath(i) );
00472 
00473          if ( isPathRelative( path ) && !isPathRelative( ConfigurationFileLocator::Instance().getConfigFileName() )) {
00474             ASCString path2 = getDirectory( ConfigurationFileLocator::Instance().getConfigFileName() );
00475             appendbackslash ( path2 );
00476             addSearchPath( path2 + path );
00477          } else
00478             addSearchPath ( path );
00479       }
00480    try {
00481      opencontainer ( "*.ascdat" );
00482    }
00483    catch ( tfileerror err ) {
00484       fatalError ( "a fatal IO error occured while mounting the container file %s\n"
00485                    "It is probably damaged, try getting a new one.\n", err.getFileName().c_str() );
00486    }
00487    catch ( tcompressionerror err ) {
00488       fatalError ( "a fatal error occured while decompressing a container file.\n"
00489                    "If you have several *.ascdat files in your ASC directory, try removing all but main.ascdat.\n"
00490                    "If the error still occurs then, get a new data package from www.asc-hq.org\n" );
00491    }
00492    catch ( ASCexception ) {
00493       fatalError ( "a fatal error occured while mounting the container files \n");
00494    }
00495    catch ( ... ) {
00496        fatalError ( "loading of game failed during pre graphic initializing" );
00497    }
00498 
00499    if ( ! (skipChecks & 1 ))
00500       checkFileLoadability ( "palette.pal" );
00501 
00502    if ( ! (skipChecks & 2 ))
00503       checkFileLoadability ( "data.version" );
00504 
00505    if ( ! (skipChecks & 8 ))
00506       checkFileLoadability ( "trrobj.version" );
00507 
00508    if ( ! (skipChecks & 0x10 ))
00509       checkFileLoadability ( "trrobj2.version" );
00510 
00511    if ( ! (skipChecks & 0x20 ))
00512       checkFileLoadability ( "buildings.version" );
00513 
00514    if ( ! (skipChecks & 0x40 ))
00515       checkFileLoadability ( "markedfielddark.png" );
00516    
00517 }
00518 
00519 void versionError( const ASCString& filename, const ASCString& location )
00520 {
00521    ASCString msg = "A newer version of the data file '";
00522    msg += filename + "' is required. \nYou can get a new data package at http://www.asc-hq.org\n";
00523    msg += "The old file is " + location;
00524    fatalError( msg );
00525 }
00526 
00527 void checkFileVersion( const ASCString& filename, const ASCString& containername, int version )
00528 {
00529    ASCString location;
00530    bool dataOk = true;
00531    if ( exist ( filename )) {
00532       tnfilestream s ( filename, tnstream::reading );
00533       ASCString str = s.readString();
00534       int v = atoi ( str.c_str() );
00535       if ( v < version )
00536          dataOk = false;
00537       location = s.getLocation();
00538    } else
00539       dataOk = false;
00540 
00541    if ( !dataOk )
00542       versionError ( containername, location );
00543 
00544 }
00545 
00546 void checkDataVersion( )
00547 {
00548    ASCString location;
00549    checkFileVersion( "main.version", "main.ascdat", 8 );
00550 
00551    if ( exist( "pbp.ascdat" ))
00552       checkFileVersion( "pbp.version", "pbp.ascdat", 26 );
00553 }
00554 

Generated on Tue Jun 24 01:27:52 2008 for Advanced Strategic Command by  doxygen 1.4.2