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

Generated on Mon May 21 01:26:37 2012 for Advanced Strategic Command by  doxygen 1.5.1