Advanced Strategic Command
sgstream.cpp
Go to the documentation of this file.
1 
8 /*
9  This file is part of Advanced Strategic Command; http://www.asc-hq.de
10  Copyright (C) 1994-2010 Martin Bickel and Marc Schellenberger
11 
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; see the file COPYING. If not, write to the
24  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
25  Boston, MA 02111-1307 USA
26 */
27 
28 
29 
30 #include <cstdlib>
31 #include <cstring>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <math.h>
35 #include <stdarg.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fstream>
39 #include <boost/regex.hpp>
40 
41 #include "global.h"
42 #include "typen.h"
43 #include "basegfx.h"
44 #include "misc.h"
45 #include "sgstream.h"
46 #include "basestrm.h"
47 #include "palette.h"
48 #include "gameoptions.h"
49 
50 #ifdef _WIN32_
51  #include <direct.h>
52  #include <windows.h>
53  #include <winreg.h>
54  #include <shlobj.h>
55 #endif
56 
57 
58 const char* asc_EnvironmentName = "ASC_CONFIGFILE";
59 int dataVersion = 0;
60 
61 const int object_version = 1;
62 const int technology_version = 1;
63 
64 
65 
66 
67 void loadpalette ( void )
68 {
69  if ( ! asc_paletteloaded ) {
70  displayLogMessage ( 4, "loading palette ... " );
71 
72  tnfilestream stream ("palette.pal", tnstream::reading);
73  stream.readdata( & pal, sizeof(pal));
74  colormixbufchar = new Uint8 [ sizeof ( tmixbuf ) ];
76  stream.readdata( colormixbuf, sizeof ( *colormixbuf ));
77 
78  for ( int i= 0; i < 8; i++ ) {
79  stream.readdata( &xlattables.xl[i], sizeof ( xlattables.a.dark05 ));
80  xlattables.xl[i][255] = 255;
81  }
82 /*
83  stream.readdata( &xlattables.a.dark1, sizeof ( xlattables.a.dark1 ));
84  xlattables.a.dark1[255] = 255;
85 
86  stream.readdata( &xlattables.a.dark2, sizeof ( xlattables.a.dark2 ));
87  xlattables.a.dark2[255] = 255;
88 
89  stream.readdata( &xlattables.a.dark3, sizeof ( xlattables.a.dark3 ));
90  xlattables.a.dark3[255] = 255;
91 
92  stream.readdata( &xlattables.light, sizeof ( xlattables.light ));
93  xlattables.light[255] = 255;
94  */
95 #ifdef use_truecolor2pal
96  stream.readdata( &truecolor2pal_table, sizeof ( truecolor2pal_table ));
97  stream.readdata( &bi2asc_color_translation_table, sizeof ( bi2asc_color_translation_table ));
98 #endif
100  // xlatpictgraytable = new tpixelxlattable;
102 
103  (*xlatpictgraytable)[255] = 255;
104 
105  asc_paletteloaded = 1;
106  displayLogMessage ( 4, "done\n" );
107  }
108 
109 }
110 
111 
112 
114 {
115 #ifdef WIN32
116  static boost::regex exevar( "\\$\\(?EXEPATH\\)?", boost::regex::icase);
117  path = boost::regex_replace( path, exevar, ConfigurationFileLocator::Instance().getExecutableLocation(), boost::regex_constants::format_literal );
118 
119  static boost::regex appdata( "\\$\\(?APPDATA\\)?", boost::regex::icase);
120  path = boost::regex_replace( path, appdata, ConfigurationFileLocator::Instance().getSpecialPath( CSIDL_APPDATA ), boost::regex_constants::format_literal );
121 
122  static boost::regex commonappdata( "\\$\\(?COMMON_APPDATA\\)?", boost::regex::icase);
123  path = boost::regex_replace( path, commonappdata, ConfigurationFileLocator::Instance().getSpecialPath( CSIDL_COMMON_APPDATA ), boost::regex_constants::format_literal );
124 
125  static boost::regex myDocs( "\\$\\(?MY_DOCUMENTS\\)?", boost::regex::icase);
126  path = boost::regex_replace( path, myDocs, ConfigurationFileLocator::Instance().getSpecialPath( CSIDL_PERSONAL ), boost::regex_constants::format_literal );
127 #endif
128 
129  /*
130  boost::smatch what;
131  if ( boost::regex_match(path, what, exevar ))
132  return boost::regex_match( ConfigurationFileLocator::Instance().getExecutableLocation() + "\\";
133 
134  static boost::regex appdata( "\\$\\(?APPDATA\\)?", boost::regex::icase);
135  if ( boost::regex_match(path, what, appdata ))
136  return ConfigurationFileLocator::Instance().getSpecialPath( CSIDL_APPDATA ) + "\\";
137 
138  static boost::regex commonappdata( "\\$\\(?COMMIN_APPDATA\\)?", boost::regex::icase);
139  if ( boost::regex_match(path, what, commonappdata ))
140  return ConfigurationFileLocator::Instance().getSpecialPath( CSIDL_COMMON_APPDATA ) + "\\" ;
141 */
142  return path;
143 }
144 
145 
146 bool makeDirectory ( const ASCString& path )
147 {
148  if ( path.empty() )
149  return false;
150 
151  ASCString path2 = resolvePath( path );
152 
153  char tmp[10000];
154  constructFileName( tmp, 0, path2.c_str(), NULL );
155 
156  int existence = directoryExist ( tmp );
157 
158  if ( !existence ) {
159  int res = createDirectory( tmp );
160  if ( res ) {
161  fprintf(stderr, "could neither access nor create directory %s\n", tmp );
162  return false;
163  }
164  }
165 
166  return true;
167 }
168 
169 
171 {
172  if ( directoryExist( filename ))
173  return filename;
174 
175  ASCString directory;
176 
177  static boost::regex dir( "(.*)[\\\\/:][^\\\\/:]+");
178  boost::smatch what;
179  if( boost::regex_match( filename, what, dir)) {
180  directory.assign( what[1].first, what[1].second );
181  return directory;
182  } else {
183  return ".";
184  }
185 }
186 
187 
189 {
190  cmdline = path;
191 }
192 
194 {
195  exePath = getDirectory( path );
196 
197 #ifdef WIN32
198  char buffer[_MAX_PATH];
199  if( _getcwd( buffer, _MAX_PATH ) )
200  if ( exePath == "." || exePath == ".\\" )
201  exePath = buffer;
202 
203 
204 #endif
205 
206 }
207 
208 
210 {
211  return exePath;
212 }
213 
214 
216 {
217 #ifdef WIN32
218  TCHAR szPath[MAX_PATH];
219 
220  if ( SUCCEEDED(SHGetFolderPath( NULL, type, NULL, SHGFP_TYPE_CURRENT, szPath ))) {
221  ASCString dir = szPath;
222  appendbackslash ( dir );
223  dir += "ASC";
224  appendbackslash ( dir );
225  return dir;
226  }
227 
228 #endif
229  return "";
230 }
231 
233 {
234  vector<ASCString> dirs;
235 
236 #ifdef _WIN32_
237  HKEY key;
238  if ( RegOpenKeyEx ( HKEY_LOCAL_MACHINE,
239  "SOFTWARE\\Advanced Strategic Command\\",
240  0,
241  KEY_READ,
242  &key ) == ERROR_SUCCESS) {
243 
244  DWORD type;
245  const int size = 2000;
246  char buf[size];
247  DWORD size2 = size;
248  if ( RegQueryValueEx ( key, "InstallDir2", NULL, &type, (BYTE*)buf, &size2 ) == ERROR_SUCCESS ) {
249  if ( type == REG_SZ ) {
250  ASCString dir = buf;
251  appendbackslash ( dir );
252  dirs.push_back( dir );
253  }
254  }
255 
256  RegCloseKey ( key );
257  }
258 
259 /*
260  ASCString dir = getSpecialPath( CSIDL_APPDATA );
261  if ( !dir.empty() )
262  dirs.push_back(dir);
263 
264  dir = getSpecialPath( CSIDL_COMMON_APPDATA );
265  if ( !dir.empty() )
266  dirs.push_back(dir);
267  */
268 
269 
270  dirs.push_back( "$(MY_DOCUMENTS)\\" );
271  dirs.push_back( "$(APPDATA)\\" );
272  dirs.push_back( "$(COMMON_APPDATA)\\" );
273  dirs.push_back( "$(EXEPATH)\\" );
274  /*
275  if ( !exePath.empty())
276  dirs.push_back( exePath );
277  */
278 
279 
280 #else
281  ASCString dir = getenv("HOME");
282  appendbackslash ( dir );
283  dir += ".asc/";
284  dirs.push_back( dir );
285 #endif
286 
287  return dirs;
288 
289 }
290 
291 
292 
293 
295 {
296  if ( cmdline.length() ) {
297  configFileType = 1;
298  displayLogMessage( 7, "ConfigurationFileLocatorCore::getConfigFileName() returns cmdline: " + cmdline + "\n" );
299  return cmdline;
300  }
301 
302  if ( getenv ( asc_EnvironmentName )) {
303  ASCString res = getenv ( asc_EnvironmentName );
304  configFileType = 2;
305  displayLogMessage( 7, "ConfigurationFileLocatorCore::getConfigFileName() returns env dir: " + res + "\n" );
306  return res;
307  }
308 
309  if ( !exePath.empty() && !isPathRelative(exePath) ) {
310  displayLogMessage( 5, "Exe path is " + exePath + "\n" );
311  ASCString completeName = exePath + "/" + asc_configurationfile;
312  if ( exist( completeName )) {
313  configFileType = 3;
314  displayLogMessage( 7, "ConfigurationFileLocatorCore::getConfigFileName() returns exepath: " + completeName + "\n" );
315  return completeName;
316  }
317  }
318 
319  vector<ASCString> list = getDefaultDirectory();
320  if ( list.size() >= 1 ) {
321  configFileType = 4;
322  for ( vector<ASCString>::iterator i = list.begin(); i != list.end(); ++i ) {
324  if( exist( p )) {
325  displayLogMessage( 7, "ConfigurationFileLocatorCore::getConfigFileName() returns default dir: " + p + "\n" );
326  return p;
327  }
328  }
329  ASCString res = resolvePath( list[0] ) + asc_configurationfile;
330  displayLogMessage( 7, "ConfigurationFileLocatorCore::getConfigFileName() returns list0: " + res + "\n" );
331  return res;
332  }
333 
334  configFileType = 5;
335  displayLogMessage( 7, "ConfigurationFileLocatorCore::getConfigFileName() returns asc_configurationfile: " + ASCString(asc_configurationfile) + "\n" );
336  return asc_configurationfile;
337 
338 }
339 
341 {
342  return "";
343 }
344 
346 {
347 }
348 
350 {
351  #ifdef WIN32
352  vector<ASCString> dirs = getDefaultDirectory();
354  for ( vector<ASCString>::iterator i = dirs.begin(); i != dirs.end(); ++i )
356  #else
358  #endif
359 }
360 
362 {
363  ASCString configFileName = ConfigurationFileLocator::Instance().getConfigFileName();
364  if ( !configFileName.empty() )
365  return configFileName ;
366  else
367  return "-none- ; default values used";
368 }
369 
370 
371 
372 int readgameoptions ( const ASCString& filename )
373 {
374  displayLogMessage ( 4, "loading game options ... " );
375 
376 
377  displayLogMessage ( 6, ASCString("Path is ") + filename + "; " );
378 
379 
380  if ( exist ( filename )) {
381  displayLogMessage ( 6, "found, " );
382  try {
383  CGameOptions::Instance()->load( filename );
384  }
385  catch ( ParsingError err ) {
386  fatalError ( "Error parsing text file " + err.getMessage() );
387  }
388  catch ( tfileerror err ) {
389  fatalError ( "Error loading file " + err.getFileName() );
390  }
391  catch ( ... ) {
392  fatalError ( "caught undefined exception" );
393  }
394 
395  } else {
396  displayLogMessage ( 6, "not found, using defaults, " );
397 
398  ConfigurationFileLocator::Instance().writeDefaultPathsToOptions();
399 
400  if ( !filename.empty() ) {
402  if ( writegameoptions( filename ))
403  displayLogMessage ( 6, "A config file has been successfully written to " + filename + " ");
404  else {
405  warningMessage("Unable to write file " + filename );
406  displayLogMessage ( 6, "Failed to write config file to " + filename + " ");
407  }
408  }
409  }
410 
411  displayLogMessage ( 4, "done\n" );
412 
414 
415  return 0;
416 }
417 
418 bool writegameoptions ( ASCString configFileName )
419 {
420  try {
421  if ( configFileName.empty() )
422  configFileName = ConfigurationFileLocator::Instance().getConfigFileName();
423 
424  configFileName = resolvePath( configFileName );
425 
426  if ( CGameOptions::Instance()->isChanged() && !configFileName.empty() ) {
427  char buf[10000];
428  if ( makeDirectory ( extractPath ( buf, configFileName.c_str() ))) {
429  CGameOptions::Instance()->save( configFileName );
430  return true;
431  }
432  }
433  }
434  catch ( ... ) {
435  // warning("Could not save game options");
436  }
437  return false;
438 }
439 
440 void checkFileLoadability ( const ASCString& filename )
441 {
442  try {
443  tnfilestream strm ( filename, tnstream::reading );
444  strm.readUint8();
445  }
446  catch ( ASCexception ) {
447  ASCString msg = "Unable to access " + filename + "\n";
448  msg += "Make sure the file main.ascdat is in one of the search paths specified in your config file !\n";
449 
450  ASCString configFileName = ConfigurationFileLocator::Instance().getConfigFileName();
451  if ( exist( configFileName ))
452  msg += "The configuration file that is used is: " + configFileName + "\n";
453  else
454  if ( !configFileName.empty() ) {
456  if ( writegameoptions( configFileName ))
457  msg += "A configuration file has been written to " + configFileName + "\n";
458  }
459 
460  msg += "These paths are being searched for data files:\n ";
461 
462  for ( int i = 0; i < getSearchPathNum(); ++i )
463  if ( !getSearchPath(i).empty() )
464  msg += getSearchPath(i) + "\n ";
465 
466  fatalError ( msg );
467  }
468  catch ( ... ) {
469  fatalError ( "checkFileLoadability threw an unspecified exception\n" );
470  }
471 }
472 
473 
474 
475 void initFileIO ( const ASCString& configFileName, int skipChecks )
476 {
477 
478  ConfigurationFileLocator::Instance().setCommandLineParam( configFileName );
479 
480  readgameoptions( ConfigurationFileLocator::Instance().getConfigFileName() );
481 
482  for ( int i = 0; i < CGameOptions::Instance()->getSearchPathNum(); i++ )
483  if ( !CGameOptions::Instance()->getSearchPath(i).empty() ) {
484  displayLogMessage ( 3, "adding search patch " + CGameOptions::Instance()->getSearchPath(i) + "\n" );
486 
487  if ( isPathRelative( path ) && !isPathRelative( ConfigurationFileLocator::Instance().getConfigFileName() )) {
488  ASCString path2 = getDirectory( ConfigurationFileLocator::Instance().getConfigFileName() );
489  appendbackslash ( path2 );
490  addSearchPath( path2 + path );
491  } else
492  addSearchPath ( path );
493  }
494  try {
495  opencontainer ( "*.ascdat" );
496  }
497  catch ( tfileerror err ) {
498  fatalError ( "a fatal IO error occured while mounting the container file %s\n"
499  "It is probably damaged, try getting a new one.\n", err.getFileName().c_str() );
500  }
501  catch ( StreamCompressionError err ) {
502  fatalError ( "a fatal error occured while decompressing a container file.\n"
503  "If you have several *.ascdat files in your ASC directory, try removing all but main.ascdat.\n"
504  "If the error still occurs then, get a new data package from www.asc-hq.org\n" );
505  }
506  catch ( ASCexception ) {
507  fatalError ( "a fatal error occured while mounting the container files \n");
508  }
509  catch ( ... ) {
510  fatalError ( "loading of game failed during pre graphic initializing" );
511  }
512 
513  if ( ! (skipChecks & 1 ))
514  checkFileLoadability ( "palette.pal" );
515 }
516 
517 void versionError( const ASCString& filename, const ASCString& location )
518 {
519  ASCString msg = "A newer version of the data file '";
520  msg += filename + "' is required. \nYou can get a new data package at http://www.asc-hq.org\n";
521  msg += "The old file is " + location;
522  fatalError( msg );
523 }
void addSearchPath(const ASCString &path)
miscellaneous functions which are used by ASC and all its tools
const int technology_version
Definition: sgstream.cpp:62
const ASCString & getFileName() const
Definition: simplestream.h:80
ASCString getSearchPath(int i)
Definition: basestrm.cpp:2539
void setDefaultDirectories()
int readdata(void *buf, int size, bool excpt=true)
Reads data from the stream.
Definition: basestrm.cpp:1698
txlattables xlattables
Definition: palette.cpp:37
void addSearchPath(const ASCString &path)
Definition: basestrm.cpp:2517
void load(const ASCString &filename)
Definition: gameoptions.cpp:71
Uint8 * colormixbufchar
Definition: palette.cpp:39
ASCString getSpecialPath(int type)
Definition: sgstream.cpp:215
tmixbuf * pmixbuf
Definition: palette.h:73
void warningMessage(const ASCString &str)
ppixelxlattable xlatpictgraytable
Definition: palette.cpp:35
Global platform dependant definitions. This file just branches to the platform specific files in thei...
void versionError(const ASCString &filename, const ASCString &location)
Definition: sgstream.cpp:517
void setExecutableLocation(const ASCString &path)
Definition: sgstream.cpp:193
int readgameoptions(const ASCString &filename)
Definition: sgstream.cpp:372
ASCString getConfigFileName()
Definition: sgstream.cpp:361
virtual Uint8 readUint8(void)
Reads a 8 bit unsigned Integer.
Definition: basestrm.cpp:305
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
char * extractPath(char *buf, const char *filename)
Definition: basestrm.cpp:2548
void checkFileLoadability(const ASCString &filename)
Definition: sgstream.cpp:440
char * malloc(int)
tpixelxlattable xl[8]
Definition: palette.h:93
void setChanged(bool flag=true)
Definition: gameoptions.h:272
bool asc_paletteloaded
Definition: palette.cpp:42
bool makeDirectory(const ASCString &path)
Definition: sgstream.cpp:146
bool directoryExist(const ASCString &path)
Definition: basestrm.cpp:2500
bool isPathRelative(const ASCString &path)
Definition: basestrm.cpp:934
tmixbuf * colormixbuf
Definition: palette.cpp:38
int getSearchPathNum()
Definition: basestrm.cpp:2534
bool writegameoptions(ASCString configFileName)
Definition: sgstream.cpp:418
void displayLogMessage(int msgVerbosity, const char *message,...)
const char * asc_EnvironmentName
Definition: sgstream.cpp:58
const int object_version
Definition: sgstream.cpp:61
The interface for the various streams that ASC offers, like file and memory streams.
int getSearchPathNum()
char * constructFileName(char *buf, int directoryLevel, const char *path, const char *filename)
Definition: basestrm.cpp:873
const ASCString & getMessage(void) const
Definition: errors.h:42
int createDirectory(const char *name)
Definition: basestrm.cpp:2609
The IO for many basic classes and structurs of ACS.
void generategrayxlattable(ppixelxlattable tab, Uint8 offset, Uint8 size, dacpalette256 *pal)
A translation table ( to be used by xlatpict ) is generated to translate any color of palette pal to ...
Definition: basegfx.cpp:44
ASCString getConfigForPrinting()
Definition: sgstream.cpp:340
static CGameOptions * Instance()
returns the only Instance
Definition: gameoptions.cpp:38
ASCString getDirectory(ASCString filename)
Definition: sgstream.cpp:170
const char * asc_configurationfile
Definition: unix/fileio.cpp:29
dacpalette256 pal
Definition: palette.cpp:33
tpixelxlattable * ppixelxlattable
Definition: palette.h:75
void opencontainer(const char *wildcard)
Definition: basestrm.cpp:2457
void appendbackslash(char *string)
Definition: basestrm.cpp:2596
basegfx.h is the interface for the legacy graphic routines (of which some are platform dependent)...
void loadpalette(void)
Definition: sgstream.cpp:67
Uint8 tmixbuf[256][256]
Definition: palette.h:72
void setCommandLineParam(const ASCString &path)
Definition: sgstream.cpp:188
ASCString getSearchPath(int i)
bool exist(const ASCString &s)
does a file s exist (wildcards allowed)
Definition: basestrm.cpp:2444
void initFileIO(const ASCString &configFileName, int skipChecks)
Definition: sgstream.cpp:475
The color palette and various color translation tables.
vector< ASCString > getDefaultDirectory()
Definition: sgstream.cpp:232
ASCString getExecutableLocation()
Definition: sgstream.cpp:209
int dataVersion
Definition: sgstream.cpp:59
void fatalError(const ASCString &string)
struct txlattables::@19::@21 a
void save(const ASCString &filename)
Definition: gameoptions.cpp:83
ASCString resolvePath(ASCString path)
Definition: sgstream.cpp:113