changeset 3628:db3c3f4d1976 draft

(svn r4527) - Feature [NewGRF]: Add support for specifying parameters to GRF files. Usage: "mygrf = 1". You can pass up to 128 parameters, each one seperated by a comma or a space-character. Big thanks to peter1138 for the inspiration and examples.
author Darkvater <Darkvater@openttd.org>
date Sat, 22 Apr 2006 13:17:13 +0000
parents 93b3dcff0408
children 0b11a7c0a0e9
files newgrf.c newgrf.h settings.c
diffstat 3 files changed, 84 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/newgrf.c
+++ b/newgrf.c
@@ -41,6 +41,7 @@
 
 static GRFFile *_cur_grffile;
 GRFFile *_first_grffile;
+GRFConfig *_first_grfconfig;
 static int _cur_spriteid;
 static int _cur_stage;
 static uint32 _nfo_line;
@@ -2492,11 +2493,11 @@
 	_cur_grffile->spritegroups_count = 0;
 }
 
-static void InitNewGRFFile(const char* filename, int sprite_offset)
+static void InitNewGRFFile(const GRFConfig *config, int sprite_offset)
 {
 	GRFFile *newfile;
 
-	newfile = GetFileByFilename(filename);
+	newfile = GetFileByFilename(config->filename);
 	if (newfile != NULL) {
 		/* We already loaded it once. */
 		newfile->sprite_offset = sprite_offset;
@@ -2508,9 +2509,14 @@
 
 	if (newfile == NULL) error ("Out of memory");
 
-	newfile->filename = strdup(filename);
+	newfile->filename = strdup(config->filename);
 	newfile->sprite_offset = sprite_offset;
 
+	/* Copy the initial parameter list */
+	assert(lengthof(newfile->param) == lengthof(config->param) && lengthof(config->param) == 0x80);
+	newfile->param_end = config->num_params;
+	memcpy(newfile->param, config->param, 0x80 * sizeof(newfile->param[0]));
+
 	if (_first_grffile == NULL) {
 		_cur_grffile = newfile;
 		_first_grffile = newfile;
@@ -2707,17 +2713,18 @@
 	_custom_sprites_base = load_index;
 	for (stage = 0; stage <= 2; stage++) {
 		uint slot = file_index;
-		uint j;
+		GRFConfig *c;
 
 		_cur_stage = stage;
 		_cur_spriteid = load_index;
-		for (j = 0; j != lengthof(_newgrf_files) && _newgrf_files[j] != NULL; j++) {
-			if (!FiosCheckFileExists(_newgrf_files[j])) {
+		for (c = _first_grfconfig; c != NULL; c = c->next) {
+			if (!FiosCheckFileExists(c->filename)) {
 				// TODO: usrerror()
-				error("NewGRF file missing: %s", _newgrf_files[j]);
+				error("NewGRF file missing: %s", c->filename);
 			}
-			if (stage == 0) InitNewGRFFile(_newgrf_files[j], _cur_spriteid);
-			LoadNewGRFFile(_newgrf_files[j], slot++, stage);
+
+			if (stage == 0) InitNewGRFFile(c, _cur_spriteid);
+			LoadNewGRFFile(c->filename, slot++, stage);
 			if (stage == 2) ClearTemporaryNewGRFData();
 			DEBUG(spritecache, 2) ("Currently %i sprites are loaded", load_index);
 		}
--- a/newgrf.h
+++ b/newgrf.h
@@ -13,14 +13,13 @@
 	struct GRFLabel *next;
 } GRFLabel;
 
-typedef struct GRFFile GRFFile;
-struct GRFFile {
+typedef struct GRFFile {
 	char *filename;
 	uint32 grfid;
 	uint16 flags;
 	uint16 sprite_offset;
 	SpriteID first_spriteset; ///< Holds the first spriteset's sprite offset.
-	GRFFile *next;
+	struct GRFFile *next;
 
 	/* A sprite group contains all sprites of a given vehicle (or multiple
 	 * vehicles) when carrying given cargo. It consists of several sprite
@@ -48,10 +47,19 @@
 	uint param_end; /// one more than the highest set parameter
 
 	GRFLabel *label; ///< Pointer to the first label. This is a linked list, not an array.
-};
+} GRFFile;
 
 extern GRFFile *_first_grffile;
 
+typedef struct GRFConfig {
+	const char *filename;
+	uint32 param[0x80];
+	byte num_params;
+
+	struct GRFConfig *next;
+} GRFConfig;
+
+extern GRFConfig *_first_grfconfig;
 
 void LoadNewGRF(uint load_index, uint file_index);
 
--- a/settings.c
+++ b/settings.c
@@ -34,6 +34,7 @@
 #include "console.h"
 #include "saveload.h"
 #include "npf.h"
+#include "newgrf.h"
 
 /** The patch values that are used for new games and/or modified in config file */
 Patches _patches_newgame;
@@ -43,6 +44,10 @@
 typedef struct IniGroup IniGroup;
 typedef struct SettingsMemoryPool SettingsMemoryPool;
 
+typedef const char *SettingListCallbackProc(const IniItem *item, uint index);
+typedef void SettingDescProc(IniFile *ini, const SettingDesc *desc, const char *grpname, void *object);
+typedef void SettingDescProcList(IniFile *ini, const char *grpname, char **list, uint len, SettingListCallbackProc proc);
+
 static void pool_init(SettingsMemoryPool **pool);
 static void *pool_alloc(SettingsMemoryPool **pool, uint size);
 static void *pool_strdup(SettingsMemoryPool **pool, const char *mem, uint size);
@@ -817,20 +822,25 @@
  * file that will be parsed
  * @param list pointer to an string(pointer) array that will store the parsed
  * entries of the given section
- * @param len the maximum number of items available for the above list */
-static void ini_load_setting_list(IniFile *ini, const char *grpname, char **list, uint len)
+ * @param len the maximum number of items available for the above list
+ * @param proc callback function that can override how the values are stored
+ * inside the list */
+static void ini_load_setting_list(IniFile *ini, const char *grpname, char **list, uint len, SettingListCallbackProc proc)
 {
 	IniGroup *group = ini_getgroup(ini, grpname, -1);
 	IniItem *item;
-	uint i;
+	const char *entry;
+	uint i, j;
 
 	if (group == NULL) return;
 
-	item = group->item;
-	for (i = 0; i != len; i++) {
-		if (item == NULL) break;
-		list[i] = strdup(item->name);
-		item = item->next;
+	for (i = j = 0, item = group->item; item != NULL; item = item->next) {
+		entry = (proc != NULL) ? proc(item, i++) : item->name;
+
+		if (entry == NULL || list == NULL) continue;
+
+		if (j == len) break;
+		list[j++] = strdup(entry);
 	}
 }
 
@@ -843,26 +853,30 @@
  * source to be saved into the relevant ini section
  * @param len the maximum number of items available for the above list
  * @param proc callback function that can will provide the source data if defined */
-static void ini_save_setting_list(IniFile *ini, const char *grpname, char **list, uint len)
+static void ini_save_setting_list(IniFile *ini, const char *grpname, char **list, uint len, SettingListCallbackProc proc)
 {
 	IniGroup *group = ini_getgroup(ini, grpname, -1);
 	IniItem *item = NULL;
+	const char *entry;
 	uint i;
 	bool first = true;
 
+	if (proc == NULL && list == NULL) return;
 	if (group == NULL) return;
 	group->item = NULL;
 
 	for (i = 0; i != len; i++) {
-		if (list[i] == NULL || list[i][0] == '\0') continue;
+		entry = (proc != NULL) ? proc(NULL, i) : list[i];
+
+		if (entry == NULL || *entry == '\0') continue;
 
 		if (first) { // add first item to the head of the group
-			item = ini_item_alloc(group, list[i], strlen(list[i]));
+			item = ini_item_alloc(group, entry, strlen(entry));
 			item->value = item->name;
 			group->item = item;
 			first = false;
 		} else { // all other items are attached to the previous one
-			item->next = ini_item_alloc(group, list[i], strlen(list[i]));
+			item->next = ini_item_alloc(group, entry, strlen(entry));
 			item = item->next;
 			item->value = item->name;
 		}
@@ -1385,8 +1399,33 @@
 #undef NO
 #undef CR
 
-typedef void SettingDescProc(IniFile *ini, const SettingDesc *desc, const char *grpname, void *object);
-typedef void SettingDescProcList(IniFile *ini, const char *grpname, char **list, uint len);
+const char *GRFProcessParams(const IniItem *item, uint index)
+{
+	GRFConfig *c;
+
+	/* Saving newgrf stuff to configuration, not done since it is kept the same */
+	if (item == NULL) return NULL;
+
+	/* Loading newgrf stuff from configuration file */
+	c = calloc(1, sizeof(*c));
+	c->filename = strdup(item->name);
+	c->num_params = parse_intlist(item->value, (int*)c->param, lengthof(c->param));
+	if (c->num_params == (byte)-1) {
+		ShowInfoF("ini: error in array '%s'", item->name);
+		c->num_params = 0;
+	}
+
+	if (_first_grfconfig == NULL) {
+		_first_grfconfig = c;
+	} else {
+		GRFConfig *c2;
+		/* Attach the label to the end of the list */
+		for (c2 = _first_grfconfig; c2->next != NULL; c2 = c2->next);
+		c2->next = c;
+	}
+
+	return c->filename;
+}
 
 /* Common handler for saving/loading variables to the configuration file */
 static void HandleSettingDescs(IniFile *ini, SettingDescProc *proc, SettingDescProcList *proc_list)
@@ -1403,8 +1442,8 @@
 
 #ifdef ENABLE_NETWORK
 	proc(ini, (const SettingDesc*)_network_settings, "network", NULL);
-	proc_list(ini, "servers", _network_host_list, lengthof(_network_host_list));
-	proc_list(ini, "bans",    _network_ban_list,  lengthof(_network_ban_list));
+	proc_list(ini, "servers", _network_host_list, lengthof(_network_host_list), NULL);
+	proc_list(ini, "bans",    _network_ban_list,  lengthof(_network_ban_list), NULL);
 #endif /* ENABLE_NETWORK */
 }
 
@@ -1413,7 +1452,7 @@
 {
 	IniFile *ini = ini_load(_config_file);
 	HandleSettingDescs(ini, ini_load_settings, ini_load_setting_list);
-	ini_load_setting_list(ini, "newgrf", _newgrf_files, lengthof(_newgrf_files));
+	ini_load_setting_list(ini, "newgrf", NULL, 0, GRFProcessParams);
 	ini_free(ini);
 }