(svn r7348) -Feature: Initial support for saving NewGRF settings with savegames. Back up your savegames...
authorpeter1138
Mon, 04 Dec 2006 08:30:04 +0000
changeset 5228 c4a780348f66
parent 5227 733a73627cb9
child 5229 95fb62dc55d7
(svn r7348) -Feature: Initial support for saving NewGRF settings with savegames. Back up your savegames...
Makefile
genworld_gui.c
newgrf.c
newgrf.h
newgrf_config.c
newgrf_config.h
newgrf_text.c
newgrf_text.h
openttd.c
openttd.vcproj
openttd_vs80.vcproj
saveload.c
settings.c
--- a/Makefile	Mon Dec 04 08:11:53 2006 +0000
+++ b/Makefile	Mon Dec 04 08:30:04 2006 +0000
@@ -733,6 +733,7 @@
 SRCS += network_udp.c
 SRCS += newgrf.c
 SRCS += newgrf_cargo.c
+SRCS += newgrf_config.c
 SRCS += newgrf_engine.c
 SRCS += newgrf_sound.c
 SRCS += newgrf_spritegroup.c
--- a/genworld_gui.c	Mon Dec 04 08:11:53 2006 +0000
+++ b/genworld_gui.c	Mon Dec 04 08:30:04 2006 +0000
@@ -22,6 +22,7 @@
 #include "network.h"
 #include "thread.h"
 #include "date.h"
+#include "newgrf_config.h"
 
 enum {
 	START_DATE_QUERY,
@@ -164,6 +165,7 @@
 	UpdatePatches();
 	_opt_ptr = &_opt;
 	*_opt_ptr = _opt_newgame;
+	ResetGRFConfig(true);
 
 	SndPlayFx(SND_15_BEEP);
 	switch (mode) {
--- a/newgrf.c	Mon Dec 04 08:11:53 2006 +0000
+++ b/newgrf.c	Mon Dec 04 08:30:04 2006 +0000
@@ -27,6 +27,7 @@
 #include "date.h"
 #include "currency.h"
 #include "sound.h"
+#include "newgrf_config.h"
 #include "newgrf_sound.h"
 #include "newgrf_spritegroup.h"
 
@@ -47,11 +48,12 @@
 
 static GRFFile *_cur_grffile;
 GRFFile *_first_grffile;
-GRFConfig *_first_grfconfig;
 static SpriteID _cur_spriteid;
 static GrfLoadingStage _cur_stage;
 static uint32 _nfo_line;
 
+static GRFConfig *_cur_grfconfig;
+
 /* Miscellaneous GRF features, set by Action 0x0D, parameter 0x9E */
 static byte _misc_grf_features = 0;
 
@@ -2450,6 +2452,27 @@
 	}
 }
 
+/* Action 0x08 (GLS_FILESCAN) */
+static void ScanInfo(byte *buf, int len)
+{
+	uint8 version;
+	uint32 grfid;
+	const char *name;
+	const char *info;
+
+	check_length(len, 8, "Info"); buf++;
+	version = grf_load_byte(&buf);
+	grfid = grf_load_dword(&buf);
+	name = (const char*)buf;
+	info = name + strlen(name) + 1;
+
+	_cur_grfconfig->grfid = grfid;
+	_cur_grfconfig->name  = TranslateTTDPatchCodes(name);
+	_cur_grfconfig->info  = TranslateTTDPatchCodes(info);
+
+	_skip_sprites = -1;
+}
+
 /* Action 0x08 */
 static void GRFInfo(byte *buf, int len)
 {
@@ -3460,25 +3483,25 @@
 	 * is not in memory and scanning the file every time would be too expensive.
 	 * In other stages we skip action 0x10 since it's already dealt with. */
 	static const SpecialSpriteHandler handlers[][GLS_END] = {
-		/* 0x00 */ { NULL,            NULL,       FeatureChangeInfo, },
-		/* 0x01 */ { NULL,            NULL,       NewSpriteSet, },
-		/* 0x02 */ { NULL,            NULL,       NewSpriteGroup, },
-		/* 0x03 */ { NULL,            NULL,       FeatureMapSpriteGroup, },
-		/* 0x04 */ { NULL,            NULL,       FeatureNewName, },
-		/* 0x05 */ { NULL,            NULL,       GraphicsNew, },
-		/* 0x06 */ { NULL,            CfgApply,   CfgApply, },
-		/* 0x07 */ { NULL,            NULL,       SkipIf, },
-		/* 0x08 */ { NULL,            GRFInfo,    GRFInfo, },
-		/* 0x09 */ { NULL,            SkipIf,     SkipIf, },
-		/* 0x0A */ { NULL,            NULL,       SpriteReplace, },
-		/* 0x0B */ { NULL,            GRFError,   GRFError, },
-		/* 0x0C */ { NULL,            GRFComment, GRFComment, },
-		/* 0x0D */ { NULL,            ParamSet,   ParamSet, },
-		/* 0x0E */ { NULL,            GRFInhibit, GRFInhibit, },
-		/* 0x0F */ { NULL,            NULL,       NULL, },
-		/* 0x10 */ { DefineGotoLabel, NULL,       NULL, },
-		/* 0x11 */ { NULL,            NULL,       GRFSound, },
-		/* 0x12 */ { NULL,            NULL,       LoadFontGlyph, },
+		/* 0x00 */ { NULL,     NULL,            NULL,       FeatureChangeInfo, },
+		/* 0x01 */ { NULL,     NULL,            NULL,       NewSpriteSet, },
+		/* 0x02 */ { NULL,     NULL,            NULL,       NewSpriteGroup, },
+		/* 0x03 */ { NULL,     NULL,            NULL,       FeatureMapSpriteGroup, },
+		/* 0x04 */ { NULL,     NULL,            NULL,       FeatureNewName, },
+		/* 0x05 */ { NULL,     NULL,            NULL,       GraphicsNew, },
+		/* 0x06 */ { NULL,     NULL,            CfgApply,   CfgApply, },
+		/* 0x07 */ { NULL,     NULL,            NULL,       SkipIf, },
+		/* 0x08 */ { ScanInfo, NULL,            GRFInfo,    GRFInfo, },
+		/* 0x09 */ { NULL,     NULL,            SkipIf,     SkipIf, },
+		/* 0x0A */ { NULL,     NULL,            NULL,       SpriteReplace, },
+		/* 0x0B */ { NULL,     NULL,            GRFError,   GRFError, },
+		/* 0x0C */ { NULL,     NULL,            GRFComment, GRFComment, },
+		/* 0x0D */ { NULL,     NULL,            ParamSet,   ParamSet, },
+		/* 0x0E */ { NULL,     NULL,            GRFInhibit, GRFInhibit, },
+		/* 0x0F */ { NULL,     NULL,            NULL,       NULL, },
+		/* 0x10 */ { NULL,     DefineGotoLabel, NULL,       NULL, },
+		/* 0x11 */ { NULL,     NULL,            NULL,       GRFSound, },
+		/* 0x12 */ { NULL,     NULL,            NULL,       LoadFontGlyph, },
 	};
 
 	byte* buf;
@@ -3520,8 +3543,9 @@
 }
 
 
-static void LoadNewGRFFile(const char *filename, uint file_index, GrfLoadingStage stage)
+void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage)
 {
+	const char *filename = config->filename;
 	uint16 num;
 
 	/* A .grf file is activated only if it was active when the game was
@@ -3533,15 +3557,17 @@
 	 * During activation, only actions 0, 1, 2, 3, 4, 5, 7, 8, 9, 0A and 0B are
 	 * carried out.  All others are ignored, because they only need to be
 	 * processed once at initialization.  */
-	if (stage != GLS_LABELSCAN) {
+	if (stage != GLS_FILESCAN && stage != GLS_LABELSCAN) {
 		_cur_grffile = GetFileByFilename(filename);
 		if (_cur_grffile == NULL) error("File ``%s'' lost in cache.\n", filename);
-		if (stage > 1 && !(_cur_grffile->flags & 0x0001)) return;
+		if (stage == GLS_ACTIVATION && !(_cur_grffile->flags & 0x0001)) return;
 	}
 
 	FioOpenFile(file_index, filename);
 	_file_index = file_index; // XXX
 
+	_cur_grfconfig = config;
+
 	DEBUG(grf, 7) ("Reading NewGRF-file '%s'", filename);
 
 	/* Skip the first sprite; we don't care about how many sprites this
@@ -3550,7 +3576,8 @@
 	if (FioReadWord() == 4 && FioReadByte() == 0xFF) {
 		FioReadDword();
 	} else {
-		error("Custom .grf has invalid format.");
+		DEBUG(grf, 7) ("Custom .grf has invalid format.");
+		return;
 	}
 
 	_skip_sprites = 0; // XXX
@@ -3616,14 +3643,16 @@
 
 		_cur_stage = stage;
 		_cur_spriteid = load_index;
-		for (c = _first_grfconfig; c != NULL; c = c->next) {
+		for (c = _grfconfig; c != NULL; c = c->next) {
+			if (HASBIT(c->flags, GCF_DISABLED) || HASBIT(c->flags, GCF_NOT_FOUND)) continue;
+
 			if (!FioCheckFileExists(c->filename)) {
 				// TODO: usrerror()
 				error("NewGRF file missing: %s", c->filename);
 			}
 
 			if (stage == GLS_LABELSCAN) InitNewGRFFile(c, _cur_spriteid);
-			LoadNewGRFFile(c->filename, slot++, stage);
+			LoadNewGRFFile(c, slot++, stage);
 			if (stage == GLS_ACTIVATION) ClearTemporaryNewGRFData();
 			DEBUG(spritecache, 2) ("Currently %i sprites are loaded", load_index);
 		}
@@ -3632,3 +3661,4 @@
 	// Pre-calculate all refit masks after loading GRF files
 	CalculateRefitMasks();
 }
+
--- a/newgrf.h	Mon Dec 04 08:11:53 2006 +0000
+++ b/newgrf.h	Mon Dec 04 08:30:04 2006 +0000
@@ -4,8 +4,10 @@
 #define NEWGRF_H
 
 #include "station.h"
+#include "newgrf_config.h"
 
 typedef enum GrfLoadingStage {
+	GLS_FILESCAN,
 	GLS_LABELSCAN,
 	GLS_INIT,
 	GLS_ACTIVATION,
@@ -58,19 +60,11 @@
 
 extern GRFFile *_first_grffile;
 
-typedef struct GRFConfig {
-	const char *filename;
-	uint32 param[0x80];
-	byte num_params;
-
-	struct GRFConfig *next;
-} GRFConfig;
-
-extern GRFConfig *_first_grfconfig;
 extern SpriteID _signal_base;
 extern SpriteID _coast_base;
 extern bool _have_2cc;
 
+void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage);
 void LoadNewGRF(uint load_index, uint file_index);
 
 #endif /* NEWGRF_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/newgrf_config.c	Mon Dec 04 08:30:04 2006 +0000
@@ -0,0 +1,294 @@
+/* $Id$ */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "functions.h"
+#include "macros.h"
+#include "debug.h"
+#include "variables.h"
+#include "saveload.h"
+#include "md5.h"
+#include "newgrf.h"
+#include "newgrf_config.h"
+
+#include "fileio.h"
+#include "fios.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef WIN32
+# include <io.h>
+#else
+# include <unistd.h>
+# include <dirent.h>
+#endif /* WIN32 */
+
+
+GRFConfig *_all_grfs;
+GRFConfig *_grfconfig;
+GRFConfig *_grfconfig_newgame;
+
+
+/* Calculate the MD5 Sum for a GRF */
+static bool CalcGRFMD5Sum(GRFConfig *config)
+{
+	FILE *f;
+	char filename[MAX_PATH];
+	md5_state_t md5state;
+	md5_byte_t buffer[1024];
+	size_t len;
+
+	/* open the file */
+	snprintf(filename, lengthof(filename), "%s%s", _path.data_dir, config->filename);
+	f = fopen(filename, "rb");
+	if (f == NULL) return false;
+
+	/* calculate md5sum */
+	md5_init(&md5state);
+	while ((len = fread(buffer, 1, sizeof(buffer), f)) != 0) {
+		md5_append(&md5state, buffer, len);
+	}
+	md5_finish(&md5state, config->md5sum);
+
+	fclose(f);
+
+	return true;
+}
+
+
+/* Find the GRFID and calculate the md5sum */
+bool FillGRFDetails(GRFConfig *config)
+{
+	if (!FioCheckFileExists(config->filename)) {
+		SETBIT(config->flags, GCF_NOT_FOUND);
+		return false;
+	}
+
+	/* Find and load the Action 8 information */
+	/* 62 is the last file slot before sample.cat.
+	 * Should perhaps be some "don't care" value */
+	LoadNewGRFFile(config, 62, GLS_FILESCAN);
+
+	/* Skip if the grfid is 0 (not read) or 0xFFFFFFFF (ttdp system grf) */
+	if (config->grfid == 0 || config->grfid == 0xFFFFFFFF) return false;
+
+	return CalcGRFMD5Sum(config);
+}
+
+
+/* Clear a GRF Config list */
+void ClearGRFConfigList(GRFConfig *config)
+{
+	GRFConfig *c, *next;
+	for (c = config; c != NULL; c = next) {
+		next = c->next;
+		free(c->filename);
+		free(c->name);
+		free(c->info);
+		free(c);
+	}
+}
+
+
+/* Copy a GRF Config list */
+static void CopyGRFConfigList(GRFConfig **dst, GRFConfig *src)
+{
+	GRFConfig *c;
+
+	for (; src != NULL; src = src->next) {
+		c = calloc(1, sizeof(*c));
+		*c = *src;
+		c->filename = strdup(src->filename);
+		if (src->name != NULL) c->name = strdup(src->name);
+		if (src->info != NULL) c->info = strdup(src->info);
+
+		*dst = c;
+		dst = &c->next;
+	}
+}
+
+
+/* Reset the current GRF Config to either blank or newgame settings */
+void ResetGRFConfig(bool defaults)
+{
+	ClearGRFConfigList(_grfconfig);
+	_grfconfig = NULL;
+	if (defaults) CopyGRFConfigList(&_grfconfig, _grfconfig_newgame);
+}
+
+
+/* Check if all GRFs in the GRF Config can be loaded */
+bool IsGoodGRFConfigList(void)
+{
+	bool res = true;
+	GRFConfig *c;
+
+	for (c = _grfconfig; c != NULL; c = c->next) {
+		const GRFConfig *f = FindGRFConfig(c->grfid, c->md5sum);
+		if (f == NULL) {
+			char buf[512], *p = buf;
+			uint i;
+
+			p += snprintf(p, lastof(buf) - p, "Couldn't find NewGRF %08X (%s) checksum ", BSWAP32(c->grfid), c->filename);
+			for (i = 0; i < lengthof(c->md5sum); i++) {
+				p += snprintf(p, lastof(buf) - p, "%02X", c->md5sum[i]);
+			}
+			ShowInfo(buf);
+
+			res = false;
+		} else {
+			DEBUG(grf, 1) ("[GRF] Loading GRF %X from %s", BSWAP32(c->grfid), f->filename);
+			c->filename = strdup(f->filename);
+			c->name     = strdup(f->name);
+			c->info     = strdup(f->info);
+		}
+	}
+
+	return res;
+}
+
+
+extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb);
+
+/* Scan a path for NewGRFs */
+static uint ScanPath(const char *path)
+{
+	uint num = 0;
+	struct stat sb;
+	struct dirent *dirent;
+	DIR *dir;
+	GRFConfig *c;
+
+	if ((dir = opendir(path)) == NULL) return 0;
+
+	while ((dirent = readdir(dir)) != NULL) {
+		const char *d_name = FS2OTTD(dirent->d_name);
+		char filename[MAX_PATH];
+
+		if (!FiosIsValidFile(path, dirent, &sb)) continue;
+
+		snprintf(filename, lengthof(filename), "%s" PATHSEP "%s", path, d_name);
+
+		if (sb.st_mode & S_IFDIR) {
+			/* Directory */
+			if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue;
+			num += ScanPath(filename);
+		} else if (sb.st_mode & S_IFREG) {
+			/* File */
+			char *ext = strrchr(filename, '.');
+			char *file = strchr(filename, PATHSEPCHAR) + 1; // Crop base path
+
+			/* If no extension or extension isn't .grf, skip the file */
+			if (ext == NULL) continue;
+			if (strcasecmp(ext, ".grf") != 0) continue;
+
+			c = calloc(1, sizeof(*c));
+			c->filename = strdup(file);
+
+			if (FillGRFDetails(c)) {
+				if (_all_grfs == NULL) {
+					_all_grfs = c;
+				} else {
+					/* Insert file into list at a position determined by its
+					 * name, so the list is sorted as we go along */
+					GRFConfig **pd, *d;
+					for (pd = &_all_grfs; (d = *pd) != NULL; pd = &d->next) {
+						if (strcasecmp(c->name, d->name) <= 0) break;
+					}
+					c->next = d;
+					*pd = c;
+				}
+
+				num++;
+			} else {
+				/* File couldn't be opened, or is either not a NewGRF or is a
+				 * 'system' NewGRF, so forget about it. */
+				free(c->filename);
+				free(c->name);
+				free(c->info);
+				free(c);
+			}
+		}
+	}
+
+	closedir(dir);
+
+	return num;
+}
+
+
+/* Scan for all NewGRFs */
+void ScanNewGRFFiles(void)
+{
+	uint num;
+
+	ClearGRFConfigList(_all_grfs);
+	_all_grfs = NULL;
+
+	DEBUG(grf, 1) ("[GRF] Scanning for NewGRFs");
+	num = ScanPath(_path.data_dir);
+	DEBUG(grf, 1) ("[GRF] Scan complete, found %d files", num);
+}
+
+
+/* Find a NewGRF in the scanned list */
+const GRFConfig *FindGRFConfig(uint32 grfid, uint8 *md5sum)
+{
+	GRFConfig *c;
+	static const uint8 blanksum[sizeof(c->md5sum)] = { 0 };
+
+	for (c = _all_grfs; c != NULL; c = c->next) {
+		if (c->grfid == grfid) {
+			if (memcmp(blanksum, c->md5sum, sizeof(c->md5sum)) == 0) CalcGRFMD5Sum(c);
+			if (memcmp(md5sum, c->md5sum, sizeof(c->md5sum)) == 0) return c;
+		}
+	}
+
+	return NULL;
+}
+
+
+static const SaveLoad _grfconfig_desc[] = {
+	SLE_STR(GRFConfig, filename,   SLE_STR, 0x40),
+	SLE_VAR(GRFConfig, grfid,      SLE_UINT32),
+	SLE_ARR(GRFConfig, md5sum,     SLE_UINT8, 16),
+	SLE_ARR(GRFConfig, param,      SLE_UINT32, 0x80),
+	SLE_VAR(GRFConfig, num_params, SLE_UINT8),
+	SLE_END()
+};
+
+
+static void Save_NGRF(void)
+{
+	GRFConfig *c;
+	int index = 0;
+
+	for (c = _grfconfig; c != NULL; c = c->next) {
+		SlSetArrayIndex(index++);
+		SlObject(c, _grfconfig_desc);
+	}
+}
+
+
+static void Load_NGRF(void)
+{
+	GRFConfig *first = NULL;
+	GRFConfig **last = &first;
+
+	while (SlIterateArray() != -1) {
+		GRFConfig *c = calloc(1, sizeof(*c));
+		SlObject(c, _grfconfig_desc);
+
+		/* Append our configuration to the list */
+		*last = c;
+		last = &c->next;
+	}
+
+	ClearGRFConfigList(_grfconfig);
+	_grfconfig = first;
+}
+
+const ChunkHandler _newgrf_chunk_handlers[] = {
+	{ 'NGRF', Save_NGRF, Load_NGRF, CH_ARRAY | CH_LAST }
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/newgrf_config.h	Mon Dec 04 08:30:04 2006 +0000
@@ -0,0 +1,43 @@
+/* $Id$ */
+
+#ifndef NEWGRF_CONFIG_H
+#define NEWGRF_CONFIG_H
+
+/* GRF config bit flags */
+enum {
+	GCF_DISABLED,
+	GCF_NOT_FOUND,
+	GCF_ACTIVATED,
+};
+
+typedef struct GRFConfig {
+	char *filename;
+	char *name;
+	char *info;
+	uint32 grfid;
+
+	uint8 flags;
+	uint8 md5sum[16];
+	uint32 param[0x80];
+	uint8 num_params;
+
+	struct GRFConfig *next;
+} GRFConfig;
+
+/* First item in list of all scanned NewGRFs */
+extern GRFConfig *_all_grfs;
+
+/* First item in list of current GRF set up */
+extern GRFConfig *_grfconfig;
+
+/* First item in list of default GRF set up */
+extern GRFConfig *_grfconfig_newgame;
+
+void ScanNewGRFFiles(void);
+const GRFConfig *FindGRFConfig(uint32 grfid, uint8 *md5sum);
+void ClearGRFConfigList(GRFConfig *config);
+void ResetGRFConfig(bool defaults);
+bool IsGoodGRFConfigList(void);
+bool FillGRFDetails(GRFConfig *config);
+
+#endif /* NEWGRF_CONFIG_H */
--- a/newgrf_text.c	Mon Dec 04 08:11:53 2006 +0000
+++ b/newgrf_text.c	Mon Dec 04 08:30:04 2006 +0000
@@ -154,7 +154,7 @@
 static byte _currentLangID = GRFLX_ENGLISH;  //by default, english is used.
 
 
-static char *TranslateTTDPatchCodes(const char *str)
+char *TranslateTTDPatchCodes(const char *str)
 {
 	char *tmp = malloc(strlen(str) * 10 + 1); /* Allocate space to allow for expansion */
 	char *d = tmp;
--- a/newgrf_text.h	Mon Dec 04 08:11:53 2006 +0000
+++ b/newgrf_text.h	Mon Dec 04 08:30:04 2006 +0000
@@ -11,5 +11,6 @@
 char *GetGRFString(char *buff, uint16 stringid, const char* last);
 void CleanUpStrings(void);
 void SetCurrentGrfLangID(const char *iso_name);
+char *TranslateTTDPatchCodes(const char *str);
 
 #endif /* NEWGRF_TEXT_H */
--- a/openttd.c	Mon Dec 04 08:11:53 2006 +0000
+++ b/openttd.c	Mon Dec 04 08:30:04 2006 +0000
@@ -53,6 +53,7 @@
 #include "date.h"
 #include "clear_map.h"
 #include "fontcache.h"
+#include "newgrf_config.h"
 
 #include <stdarg.h>
 
@@ -281,6 +282,7 @@
 	_game_mode = GM_MENU;
 	CLRBITS(_display_opt, DO_TRANS_BUILDINGS); // don't make buildings transparent in intro
 	_opt_ptr = &_opt_newgame;
+	ResetGRFConfig(false);
 
 	// Setup main window
 	ResetWindowSystem();
@@ -451,7 +453,10 @@
 
 	NetworkStartUp(); // initialize network-core
 
+	ScanNewGRFFiles();
+
 	_opt_ptr = &_opt_newgame;
+	ResetGRFConfig(false);
 
 	/* XXX - ugly hack, if diff_level is 9, it means we got no setting from the config file */
 	if (_opt_newgame.diff_level == 9) SetDifficultyLevel(0, &_opt_newgame);
@@ -754,6 +759,7 @@
 
 	case SM_LOAD: { /* Load game, Play Scenario */
 		_opt_ptr = &_opt;
+		ResetGRFConfig(true);
 
 		if (!SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL)) {
 			LoadIntroGame();
@@ -793,6 +799,7 @@
 			Player *p;
 
 			_opt_ptr = &_opt;
+			ResetGRFConfig(true);
 
 			_local_player = OWNER_NONE;
 			_generating_world = true;
@@ -1149,6 +1156,9 @@
 	// convert road side to my format.
 	if (_opt.road_side) _opt.road_side = 1;
 
+	/* Check all NewGRFs are present */
+	if (!IsGoodGRFConfigList()) return false;
+
 	// Load the sprites
 	GfxLoadSprites();
 	LoadStringWidthTable();
--- a/openttd.vcproj	Mon Dec 04 08:11:53 2006 +0000
+++ b/openttd.vcproj	Mon Dec 04 08:30:04 2006 +0000
@@ -316,6 +316,9 @@
 				RelativePath=".\newgrf_cargo.c">
 			</File>
 			<File
+				RelativePath=".\newgrf_config.c">
+			</File>
+			<File
 				RelativePath=".\newgrf_engine.c">
 			</File>
 			<File
@@ -572,6 +575,9 @@
 				RelativePath=".\newgrf_cargo.h">
 			</File>
 			<File
+				RelativePath=".\newgrf_config.h">
+			</File>
+			<File
 				RelativePath=".\newgrf_engine.h">
 			</File>
 			<File
--- a/openttd_vs80.vcproj	Mon Dec 04 08:11:53 2006 +0000
+++ b/openttd_vs80.vcproj	Mon Dec 04 08:30:04 2006 +0000
@@ -669,6 +669,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\newgrf_config.c"
+				>
+			</File>
+			<File
 				RelativePath=".\newgrf_engine.c"
 				>
 			</File>
@@ -1060,6 +1064,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\newgrf_config.h"
+				>
+			</File>
+			<File
 				RelativePath=".\newgrf_engine.h"
 				>
 			</File>
--- a/saveload.c	Mon Dec 04 08:11:53 2006 +0000
+++ b/saveload.c	Mon Dec 04 08:30:04 2006 +0000
@@ -30,7 +30,7 @@
 #include "variables.h"
 #include <setjmp.h>
 
-const uint16 SAVEGAME_VERSION = 40;
+const uint16 SAVEGAME_VERSION = 41;
 uint16 _sl_version;       /// the major savegame version identifier
 byte   _sl_minor_version; /// the minor savegame version, DO NOT USE!
 
@@ -1200,6 +1200,7 @@
 extern const ChunkHandler _industry_chunk_handlers[];
 extern const ChunkHandler _economy_chunk_handlers[];
 extern const ChunkHandler _animated_tile_chunk_handlers[];
+extern const ChunkHandler _newgrf_chunk_handlers[];
 
 static const ChunkHandler * const _chunk_handlers[] = {
 	_misc_chunk_handlers,
@@ -1216,6 +1217,7 @@
 	_station_chunk_handlers,
 	_player_chunk_handlers,
 	_animated_tile_chunk_handlers,
+	_newgrf_chunk_handlers,
 	NULL,
 };
 
--- a/settings.c	Mon Dec 04 08:11:53 2006 +0000
+++ b/settings.c	Mon Dec 04 08:30:04 2006 +0000
@@ -36,6 +36,7 @@
 #include "npf.h"
 #include "yapf/yapf.h"
 #include "newgrf.h"
+#include "newgrf_config.h"
 #include "genworld.h"
 #include "date.h"
 #include "rail.h"
@@ -1504,6 +1505,7 @@
 	/* Loading newgrf stuff from configuration file */
 	c = calloc(1, sizeof(*c));
 	c->filename = strdup(item->name);
+	FillGRFDetails(c);
 
 	if (*item->value != '\0') {
 		c->num_params = parse_intlist(item->value, (int*)c->param, lengthof(c->param));
@@ -1513,12 +1515,12 @@
 		}
 	}
 
-	if (_first_grfconfig == NULL) {
-		_first_grfconfig = c;
+	if (_grfconfig_newgame == NULL) {
+		_grfconfig_newgame = c;
 	} else {
 		GRFConfig *c2;
 		/* Attach the label to the end of the list */
-		for (c2 = _first_grfconfig; c2->next != NULL; c2 = c2->next);
+		for (c2 = _grfconfig_newgame; c2->next != NULL; c2 = c2->next);
 		c2->next = c;
 	}