TORCS  1.3.9
The Open Racing Car Simulator
main.cpp
Go to the documentation of this file.
1 /***************************************************************************
2 
3  file : main.cpp
4  created : Sat Sep 2 10:40:47 CEST 2000
5  copyright : (C) 2000-2014 by Patrice & Eric Espie, Bernhard Wymann
6  email : torcs@free.fr
7  version : $Id$
8 
9  ***************************************************************************/
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  ***************************************************************************/
19 
20 #ifdef WIN32
21 #include <windows.h>
22 #include <stdlib.h>
23 #include <shlobj.h>
24 #endif
25 #include <GL/glut.h>
26 #include <tgfclient.h>
27 #include <client.h>
28 #include <portability.h>
29 #include <raceinit.h>
30 
31 #include "windowsspec.h"
32 
33 
34 // replace '\' with '/'
35 static void convertDelimiter(char* buf, const int bufsize)
36 {
37  int i;
38  for (i = 0; i < bufsize && buf[i] != '\0'; i++) {
39  if (buf[i] == '\\') {
40  buf[i] = '/';
41  }
42  }
43 }
44 
45 
46 static void copyFileIfNotExists(const char* filepath)
47 {
48  static const int BUFSIZE = 1024;
49  char target[BUFSIZE];
50  snprintf(target, BUFSIZE, "%s%s", GetLocalDir(), filepath);
51  target[BUFSIZE-1] = '\0';
52 
53  DWORD attr = GetFileAttributes(target);
54  DWORD error = GetLastError();
55  if (
56  attr == INVALID_FILE_ATTRIBUTES &&
57  (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND)
58  ) {
59  if (GfCreateDirForFile(target) == GF_DIR_CREATED) {
60  char source[BUFSIZE];
61  snprintf(source, BUFSIZE, "%s%s", GetDataDir(), filepath);
62  source[BUFSIZE-1] = '\0';
63  if (SUCCEEDED(CopyFile(source, target, TRUE))) {
64  GfOut("Copy success: %s\n", target);
65  } else {
66  GfError("Copy failed: %s\n", target);
67  }
68  } else {
69  GfError("Target directory creation failed: %s\n", target);
70  }
71  }
72 }
73 
74 
75 // Check/prepare expected files in LocalDir
76 static void prepareLocalDir()
77 {
78  const char* file[] = {
79  "drivers/human/car.xml",
80  "drivers/human/human.xml",
81  "drivers/human/preferences.xml",
82  "config/graph.xml",
83  "config/raceengine.xml",
84  "config/screen.xml",
85  "config/sound.xml",
86  "config/style.xsl"
87  };
88 
89  int i;
90  for (i = 0; i < sizeof(file)/sizeof(file[0]); i++) {
91  copyFileIfNotExists(file[i]);
92  }
93 
94  // Copy race manager configurations
95  static const int BUFSIZE = 1024;
96  char path[BUFSIZE];
97 
98  const char* racemanpath = "config/raceman";
99  tFList *racemanList = GfDirGetListFiltered(racemanpath, "xml");
100  tFList* racemanCur = racemanList;
101 
102  if (racemanList) {
103  do {
104  snprintf(path, BUFSIZE, "%s/%s", racemanpath, racemanCur->name);
105  path[BUFSIZE-1] = '\0';
106  copyFileIfNotExists(path);
107  racemanCur = racemanCur->next;
108  } while (racemanCur != racemanList);
109  }
110 
111  GfDirFreeList(racemanList, NULL, true, true);
112 }
113 
114 
115 // Try to set the users local application data directory
116 static void setUserLocalDir(char* buf, const int bufsize)
117 {
118  TCHAR szLocalAppDataPath[MAX_PATH];
119  if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, szLocalAppDataPath))) {
120  convertDelimiter(szLocalAppDataPath, MAX_PATH);
121  snprintf(buf, bufsize, "%s/torcs/", szLocalAppDataPath);
122  if (GfCreateDir(buf) == GF_DIR_CREATED) {
123  SetLocalDir(buf);
124  prepareLocalDir();
125  }
126  }
127 }
128 
129 
130 static void init_args(int argc, char **argv, const char** raceconfig)
131 {
132  int i = 1;
133 
134  while (i < argc) {
135  if ((strncmp(argv[i], "-s", 2) == 0) || (strncmp(argv[i], "/s", 2) == 0)) {
136  i++;
138  } else if ((strncmp(argv[i], "-r", 2) == 0) || (strncmp(argv[i], "/r", 2) == 0)) {
139  i++;
140  *raceconfig = "";
141  if (i < argc) {
142  convertDelimiter(argv[i], strlen(argv[i]));
143  *raceconfig = argv[i];
144  i++;
145  }
146 
147  if ((strlen(*raceconfig) == 0) || (strstr(*raceconfig, ".xml") == 0)) {
148  printf("Please specify a race configuration xml when using -r\n");
149  exit(1);
150  }
151  } else {
152  i++; // Ignore unknown arguments
153  }
154  }
155 
156  static const int BUFSIZE = 1024;
157  char buf[BUFSIZE];
158  strncpy(buf, argv[0], BUFSIZE);
159  buf[BUFSIZE-1] = '\0'; // Guarantee zero termination for next operation.
160  char *end = strrchr(buf, '\\');
161 
162  // Did we find the last '\' and do we get a complete path?
163  if (end != NULL && buf[1] == ':') {
164  end++;
165  *(end) = '\0';
166  convertDelimiter(buf, BUFSIZE);
167 
168  // Set fallback for local directory
169  SetLocalDir(buf);
170  // Set library and data directory
171  SetDataDir(buf);
172  SetLibDir("");
173  setUserLocalDir(buf, BUFSIZE);
174  } else {
175  if (_fullpath(buf, argv[0], BUFSIZE) != NULL &&
176  (strcmp(argv[0], "wtorcs") == 0 ||
177  strcmp(argv[0], "wtorcs.exe") == 0)
178  )
179  {
180  end = strrchr(buf, '\\');
181  end++;
182  *(end) = '\0';
183  convertDelimiter(buf, BUFSIZE);
184 
185  // Set fallback for local directory
186  SetLocalDir(buf);
187  // Set library and data directory
188  SetDataDir(buf);
189  SetLibDir("");
190  setUserLocalDir(buf, BUFSIZE);
191  } else {
192  printf("Run wtorcs.exe either from the GUI or from the directory which contains wtorcs.exe\n");
193  exit(1);
194  }
195  }
196 }
197 
198 /*
199  * Function
200  * main
201  *
202  * Description
203  * Win32 entry point of TORCS
204  *
205  * Parameters
206  *
207  *
208  * Return
209  *
210  *
211  * Remarks
212  *
213  */
214 int
215 main(int argc, char *argv[])
216 {
217  const char* raceconfig = "";
218 
219  WindowsSpecInit(); /* init specific windows functions */
220  init_args(argc, argv, &raceconfig);
221 
222  if (strlen(raceconfig) == 0) {
223  GfScrInit(argc, argv); /* init screen */
224  TorcsEntry(); /* launch TORCS */
225  glutMainLoop(); /* event loop of glut */
226  } else {
227  // Run race from console, no Window, no OpenGL/OpenAL etc.
228  // Thought for blind scripted AI training
229  ReRunRaceOnConsole(raceconfig);
230  }
231 
232  return 0; /* just for the compiler, never reached */
233 }
234 
#define GfError
Definition: tgf.h:351
tFList * GfDirGetListFiltered(const char *dir, const char *suffix)
Get the list of files with matching suffix of a given directory.
Definition: directory.cpp:59
void ReRunRaceOnConsole(const char *raceconfig)
Definition: raceinit.cpp:159
char * GetLocalDir(void)
Definition: tgf.cpp:231
int GfCreateDir(char *path)
Create directory for given path recursively, so all missing parent directories are created as well...
Definition: tgf.cpp:309
List of (DLL) files for a Directory.
Definition: tgf.h:229
The Gaming Framework API (client part).
struct FList * next
Next entry.
Definition: tgf.h:231
int main(int argc, char *argv[])
Definition: main.cpp:124
char * GetDataDir(void)
Definition: tgf.cpp:257
#define GfOut
Definition: tgf.h:373
void SetSingleTextureMode(void)
Definition: tgf.cpp:279
void SetLibDir(char *buf)
Definition: tgf.cpp:250
static void convertDelimiter(char *buf, const int bufsize)
Definition: main.cpp:35
void GfScrInit(int argc, char *argv[])
Definition: screen.cpp:261
void GfDirFreeList(tFList *list, tfDirfreeUserData freeUserData, bool freename, bool freedispname)
Free a directory list.
Definition: directory.cpp:76
static void copyFileIfNotExists(const char *filepath)
Definition: main.cpp:46
void SetDataDir(char *buf)
Definition: tgf.cpp:263
static void setUserLocalDir(char *buf, const int bufsize)
Definition: main.cpp:116
char * name
File name.
Definition: tgf.h:233
void SetLocalDir(char *buf)
Definition: tgf.cpp:237
int GfCreateDirForFile(const char *filenameandpath)
Create directory for given file path recursively, so all missing parent directories are created as we...
Definition: tgf.cpp:364
void TorcsEntry(void)
Definition: entry.cpp:46
static void prepareLocalDir()
Definition: main.cpp:76
#define GF_DIR_CREATED
Definition: tgf.h:623
static void init_args(int argc, char **argv, const char **raceconfig)
Definition: main.cpp:130