Changeset - r6873:011bb2269607
[Not reviewed]
master
0 6 0
maedhros - 17 years ago 2007-06-12 13:22:14
maedhros@openttd.org
(svn r10114) -Fix: Only load newgrf error messages if the language matches the current
language. Since only one error can be loaded anyway, if the language didn't
match you'd get "Undefined string". Also since we're only loading one language
there's no need to use AddGRFString any more.
6 files changed with 41 insertions and 17 deletions:
0 comments (0 inline, 0 general)
src/newgrf.cpp
Show inline comments
 
/* $Id$ */
 

	
 
/** @file newgrf.cpp */
 

	
 
#include "stdafx.h"
 

	
 
#include <stdarg.h>
 

	
 
#include "openttd.h"
 
#include "debug.h"
 
#include "gfx.h"
 
#include "fileio.h"
 
#include "functions.h"
 
#include "engine.h"
 
#include "spritecache.h"
 
#include "station.h"
 
#include "sprite.h"
 
#include "newgrf.h"
 
#include "variables.h"
 
#include "string.h"
 
#include "strings.h"
 
#include "table/strings.h"
 
#include "bridge.h"
 
#include "town.h"
 
#include "economy.h"
 
#include "newgrf_engine.h"
 
#include "vehicle.h"
 
#include "newgrf_text.h"
 
#include "table/sprites.h"
 
#include "fontcache.h"
 
#include "date.h"
 
#include "currency.h"
 
#include "landscape.h"
 
#include "sound.h"
 
#include "newgrf_config.h"
 
#include "newgrf_house.h"
 
#include "newgrf_sound.h"
 
#include "newgrf_spritegroup.h"
 
#include "helpers.hpp"
 
#include "table/town_land.h"
 
#include "cargotype.h"
 
#include "industry.h"
 
#include "newgrf_canal.h"
 
#include "newgrf_commons.h"
 

	
 
/* TTDPatch extended GRF format codec
 
 * (c) Petr Baudis 2004 (GPL'd)
 
 * Changes by Florian octo Forster are (c) by the OpenTTD development team.
 
 *
 
 * Contains portions of documentation by TTDPatch team.
 
 * Thanks especially to Josef Drexler for the documentation as well as a lot
 
 * of help at #tycoon. Also thanks to Michael Blunck for is GRF files which
 
 * served as subject to the initial testing of this codec. */
 

	
 

	
 
static int _skip_sprites; // XXX
 
static uint _file_index; // XXX
 
SpriteID _signal_base;
 
SpriteID _coast_base;
 

	
 
static GRFFile *_cur_grffile;
 
GRFFile *_first_grffile;
 
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 */
 
@@ -3367,165 +3368,158 @@ static void SkipActA(byte *buf, int len)
 
{
 
	buf++;
 
	uint8 num_sets = grf_load_byte(&buf);
 

	
 
	for (uint i = 0; i < num_sets; i++) {
 
		/* Skip the sprites this replaces */
 
		_skip_sprites += grf_load_byte(&buf);
 
		/* But ignore where they go */
 
		grf_load_word(&buf);
 
	}
 

	
 
	grfmsg(3, "SkipActA: Skipping %d sprites", _skip_sprites);
 
}
 

	
 
/* Action 0x0B */
 
static void GRFLoadError(byte *buf, int len)
 
{
 
	/* <0B> <severity> <language-id> <message-id> [<message...> 00] [<data...>] 00 [<parnum>]
 
	 *
 
	 * B severity      00: notice, contine loading grf file
 
	 *                 01: warning, continue loading grf file
 
	 *                 02: error, but continue loading grf file, and attempt
 
	 *                     loading grf again when loading or starting next game
 
	 *                 03: error, abort loading and prevent loading again in
 
	 *                     the future (only when restarting the patch)
 
	 * B language-id   see action 4, use 1F for built-in error messages
 
	 * B message-id    message to show, see below
 
	 * S message       for custom messages (message-id FF), text of the message
 
	 *                 not present for built-in messages.
 
	 * V data          additional data for built-in (or custom) messages
 
	 * B parnum        parameter numbers to be shown in the message (maximum of 2) */
 

	
 
	static const StringID msgstr[] = {
 
		STR_NEWGRF_ERROR_VERSION_NUMBER,
 
		STR_NEWGRF_ERROR_DOS_OR_WINDOWS,
 
		STR_NEWGRF_ERROR_UNSET_SWITCH,
 
		STR_NEWGRF_ERROR_INVALID_PARAMETER,
 
		STR_NEWGRF_ERROR_LOAD_BEFORE,
 
		STR_NEWGRF_ERROR_LOAD_AFTER
 
	};
 

	
 
	static const StringID sevstr[] = {
 
		STR_NEWGRF_ERROR_MSG_INFO,
 
		STR_NEWGRF_ERROR_MSG_WARNING,
 
		STR_NEWGRF_ERROR_MSG_ERROR,
 
		STR_NEWGRF_ERROR_MSG_FATAL
 
	};
 

	
 
	/* AddGRFString expects the string to be referred to by an id in the newgrf
 
	 * file. Errors messages are never referred to however, so invent ids that
 
	 * are unlikely to be reached in a newgrf file so they don't overwrite
 
	 * anything else. */
 
	enum {
 
		MESSAGE_STRING_ID = MAX_UVALUE(StringID) - 1,
 
		MESSAGE_DATA_ID   = MAX_UVALUE(StringID)
 
	};
 

	
 
	if (!check_length(len, 6, "GRFLoadError")) return;
 

	
 
	/* For now we can only show one message per newgrf file. */
 
	if (_cur_grfconfig->error != NULL) return;
 

	
 
	buf++; // Skip the action byte.
 
	byte severity   = grf_load_byte(&buf);
 
	byte lang       = grf_load_byte(&buf);
 
	byte message_id = grf_load_byte(&buf);
 
	len -= 4;
 

	
 
	/* Skip the error if it isn't valid for the current language. */
 
	if (!CheckGrfLangID(lang, _cur_grffile->grf_version)) return;
 

	
 
	/* Skip the error until the activation stage unless bit 7 of the severity
 
	 * is set. */
 
	if (!HASBIT(severity, 7) && _cur_stage == GLS_INIT) {
 
		grfmsg(7, "GRFLoadError: Skipping non-fatal GRFLoadError in stage %d", _cur_stage);
 
		return;
 
	}
 
	CLRBIT(severity, 7);
 

	
 
	if (severity >= lengthof(sevstr)) {
 
		grfmsg(7, "GRFLoadError: Invalid severity id %d. Setting to 2 (non-fatal error).", severity);
 
		severity = 2;
 
	} else if (severity == 3) {
 
		/* This is a fatal error, so make sure the GRF is deactivated and no
 
		 * more of it gets loaded. */
 
		_cur_grfconfig->status = GCS_DISABLED;
 

	
 
		_skip_sprites = -1;
 
	}
 

	
 
	if (message_id >= lengthof(msgstr) && message_id != 0xFF) {
 
		grfmsg(7, "GRFLoadError: Invalid message id.");
 
		return;
 
	}
 

	
 
	if (len <= 1) {
 
		grfmsg(7, "GRFLoadError: No message data supplied.");
 
		return;
 
	}
 

	
 
	bool new_scheme = _cur_grffile->grf_version >= 7;
 
	GRFError *error = CallocT<GRFError>(1);
 

	
 
	error->severity = sevstr[severity];
 

	
 
	if (message_id == 0xFF) {
 
		/* This is a custom error message. */
 
		const char *message = grf_load_string(&buf, len);
 
		len -= (strlen(message) + 1);
 

	
 
		error->message = AddGRFString(_cur_grffile->grfid, MESSAGE_STRING_ID, lang, new_scheme, message, STR_UNDEFINED);
 
		error->custom_message = TranslateTTDPatchCodes(message);
 
	} else {
 
		error->message = msgstr[message_id];
 
	}
 

	
 
	if (len > 0) {
 
		const char *data = grf_load_string(&buf, len);
 
		len -= (strlen(data) + 1);
 

	
 
		error->data = AddGRFString(_cur_grffile->grfid, MESSAGE_DATA_ID, lang, new_scheme, data, STR_UNDEFINED);
 
		error->data = TranslateTTDPatchCodes(data);
 
	}
 

	
 
	/* Only two parameter numbers can be used in the string. */
 
	uint i = 0;
 
	for (; i < 2 && len > 0; i++) {
 
		error->param_number[i] = grf_load_byte(&buf);
 
		len--;
 
	}
 
	error->num_params = i;
 

	
 
	_cur_grfconfig->error = error;
 
}
 

	
 
/* Action 0x0C */
 
static void GRFComment(byte *buf, int len)
 
{
 
	/* <0C> [<ignored...>]
 
	 *
 
	 * V ignored       Anything following the 0C is ignored */
 

	
 
	if (len == 1) return;
 

	
 
	int text_len = len - 1;
 
	const char *text = (const char*)(buf + 1);
 
	grfmsg(2, "GRFComment: %.*s", text_len, text);
 
}
 

	
 
/* Action 0x0D (GLS_SAFETYSCAN) */
 
static void SafeParamSet(byte *buf, int len)
 
{
 
	if (!check_length(len, 5, "SafeParamSet")) return;
 
	buf++;
 
	uint8 target = grf_load_byte(&buf);
 

	
 
	/* Only writing GRF parameters is considered safe */
 
	if (target < 0x80) return;
 

	
 
	/* GRM could be unsafe, but as here it can only happen after other GRFs
 
	 * are loaded, it should be okay. If the GRF tried to use the slots it
 
	 * reserved, it would be marked unsafe anyway. GRM for (e.g. bridge)
 
	 * sprites  is considered safe. */
 

	
 
	SETBIT(_cur_grfconfig->flags, GCF_UNSAFE);
 

	
 
	/* Skip remainder of GRF */
 
	_skip_sprites = -1;
 
}
 

	
 
@@ -4071,98 +4065,102 @@ static void LoadFontGlyph(byte *buf, int
 
	 * W base_char    First character index */
 

	
 
	buf++; len--;
 
	if (!check_length(len, 1, "LoadFontGlyph")) return;
 

	
 
	uint8 num_def = grf_load_byte(&buf);
 

	
 
	if (!check_length(len, 1 + num_def * 4, "LoadFontGlyph")) return;
 

	
 
	for (uint i = 0; i < num_def; i++) {
 
		FontSize size    = (FontSize)grf_load_byte(&buf);
 
		uint8  num_char  = grf_load_byte(&buf);
 
		uint16 base_char = grf_load_word(&buf);
 

	
 
		grfmsg(7, "LoadFontGlyph: Loading %u glyph(s) at 0x%04X for size %u", num_char, base_char, size);
 

	
 
		for (uint c = 0; c < num_char; c++) {
 
			SetUnicodeGlyph(size, base_char + c, _cur_spriteid);
 
			LoadNextSprite(_cur_spriteid++, _file_index);
 
			_nfo_line++;
 
		}
 
	}
 
}
 

	
 
/* Action 0x13 */
 
static void TranslateGRFStrings(byte *buf, int len)
 
{
 
	/* <13> <grfid> <num-ent> <offset> <text...>
 
	 *
 
	 * 4*B grfid     The GRFID of the file whose texts are to be translated
 
	 * B   num-ent   Number of strings
 
	 * W   offset    First text ID
 
	 * S   text...   Zero-terminated strings */
 

	
 
	buf++; len--;
 
	if (!check_length(len, 7, "TranslateGRFString")) return;
 

	
 
	uint32 grfid = grf_load_dword(&buf);
 
	const GRFConfig *c = GetGRFConfig(grfid);
 
	if (c == NULL || (c->status != GCS_INITIALISED && c->status != GCS_ACTIVATED)) {
 
		grfmsg(7, "TranslateGRFStrings: GRFID 0x%08x unknown, skipping action 13", BSWAP32(grfid));
 
		return;
 
	}
 

	
 
	if (c->status == GCS_INITIALISED) {
 
		/* If the file is not active but will be activated later, give an error
 
		 * and disable this file. */
 
		GRFError *error = CallocT<GRFError>(1);
 

	
 
		char tmp[256];
 
		GetString(tmp, STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE, lastof(tmp));
 
		error->data = strdup(tmp);
 

	
 
		error->message  = STR_NEWGRF_ERROR_LOAD_AFTER;
 
		error->data     = STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE;
 
		error->severity = STR_NEWGRF_ERROR_MSG_FATAL;
 

	
 
		if (_cur_grfconfig->error != NULL) free(_cur_grfconfig->error);
 
		_cur_grfconfig->error = error;
 

	
 
		_cur_grfconfig->status = GCS_DISABLED;
 
		_skip_sprites = -1;
 
		return;
 
	}
 

	
 
	byte num_strings = grf_load_byte(&buf);
 
	uint16 first_id  = grf_load_word(&buf);
 

	
 
	if (!((first_id >= 0xD000 && first_id + num_strings <= 0xD3FF) || (first_id >= 0xDC00 && first_id + num_strings <= 0xDCFF))) {
 
		grfmsg(7, "TranslateGRFStrings: Attempting to set out-of-range string IDs in action 13 (first: 0x%4X, number: 0x%2X)", first_id, num_strings);
 
		return;
 
	}
 

	
 
	len -= 7;
 

	
 
	for (uint i = 0; i < num_strings && len > 0; i++) {
 
		const char *string   = grf_load_string(&buf, len);
 
		size_t string_length = strlen(string) + 1;
 

	
 
		len -= (int)string_length;
 

	
 
		if (string_length == 1) {
 
			grfmsg(7, "TranslateGRFString: Ignoring empty string.");
 
			continue;
 
		}
 

	
 
		/* Since no language id is supplied this string has to be added as a
 
		 * generic string, thus the language id of 0x7F. For this to work
 
		 * new_scheme has to be true as well. A language id of 0x7F will be
 
		 * overridden by a non-generic id, so this will not change anything if
 
		 * a string has been provided specifically for this language. */
 
		AddGRFString(grfid, first_id + i, 0x7F, true, string, STR_UNDEFINED);
 
	}
 
}
 

	
 
/* 'Action 0xFF' */
 
static void GRFDataBlock(byte *buf, int len)
 
{
 
	if (_grf_data_blocks == 0) {
 
		grfmsg(2, "GRFDataBlock: unexpected data block, skipping");
 
		return;
 
	}
 

	
 
@@ -4357,96 +4355,98 @@ static void ResetCustomIndustries()
 
						/* remove the layouts pointers */
 
						free((IndustryTileTable**)ind->table);
 
						ind->table = NULL;
 
					}
 

	
 
					free(ind);
 
					ind = NULL;
 
				}
 
			}
 

	
 
			free(file->industryspec);
 
			file->industryspec = NULL;
 
		}
 

	
 
		if (file->indtspec != NULL) {
 
			for (i = 0; i < NUM_INDUSTRYTILES; i++) {
 
				if (file->indtspec[i] != NULL) {
 
					free(file->indtspec[i]);
 
					file->indtspec[i] = NULL;
 
				}
 
			}
 

	
 
			free(file->indtspec);
 
			file->indtspec = NULL;
 
		}
 
	}
 
}
 

	
 
static void ResetNewGRF()
 
{
 
	GRFFile *next;
 

	
 
	for (GRFFile *f = _first_grffile; f != NULL; f = next) {
 
		next = f->next;
 

	
 
		free(f->filename);
 
		free(f->cargo_list);
 
		free(f);
 
	}
 

	
 
	_first_grffile = NULL;
 
	_cur_grffile   = NULL;
 
}
 

	
 
static void ResetNewGRFErrors()
 
{
 
	for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
 
		if (!HASBIT(c->flags, GCF_COPY) && c->error != NULL) {
 
			free(c->error->custom_message);
 
			free(c->error->data);
 
			free(c->error);
 
			c->error = NULL;
 
		}
 
	}
 
}
 

	
 
/**
 
 * Reset all NewGRF loaded data
 
 * TODO
 
 */
 
static void ResetNewGRFData()
 
{
 
	CleanUpStrings();
 

	
 
	/* Copy/reset original engine info data */
 
	memcpy(&_engine_info, &orig_engine_info, sizeof(orig_engine_info));
 
	memcpy(&_rail_vehicle_info, &orig_rail_vehicle_info, sizeof(orig_rail_vehicle_info));
 
	memcpy(&_ship_vehicle_info, &orig_ship_vehicle_info, sizeof(orig_ship_vehicle_info));
 
	memcpy(&_aircraft_vehicle_info, &orig_aircraft_vehicle_info, sizeof(orig_aircraft_vehicle_info));
 
	memcpy(&_road_vehicle_info, &orig_road_vehicle_info, sizeof(orig_road_vehicle_info));
 

	
 
	/* Copy/reset original bridge info data
 
	 * First, free sprite table data */
 
	for (uint i = 0; i < MAX_BRIDGES; i++) {
 
		if (_bridge[i].sprite_table != NULL) {
 
			for (uint j = 0; j < 7; j++) free(_bridge[i].sprite_table[j]);
 
			free(_bridge[i].sprite_table);
 
		}
 
	}
 
	memcpy(&_bridge, &orig_bridge, sizeof(_bridge));
 

	
 
	/* Reset refit/cargo class data */
 
	memset(&cargo_allowed, 0, sizeof(cargo_allowed));
 
	memset(&cargo_disallowed, 0, sizeof(cargo_disallowed));
 

	
 
	/* Reset GRM reservations */
 
	memset(&_grm_engines, 0, sizeof(_grm_engines));
 
	memset(&_grm_cargos, 0, sizeof(_grm_cargos));
 

	
 
	/* Unload sprite group data */
 
	UnloadWagonOverrides();
 
	UnloadRotorOverrideSprites();
 
	UnloadCustomEngineSprites();
 
	UnloadCustomEngineNames();
 
	ResetEngineListOrder();
 

	
 
	/* Reset price base data */
 
	ResetPriceBaseMultipliers();
src/newgrf_config.cpp
Show inline comments
 
@@ -52,133 +52,140 @@ static bool CalcGRFMD5Sum(GRFConfig *con
 

	
 
	fclose(f);
 

	
 
	return true;
 
}
 

	
 

	
 
/* Find the GRFID and calculate the md5sum */
 
bool FillGRFDetails(GRFConfig *config, bool is_static)
 
{
 
	if (!FioCheckFileExists(config->full_path)) {
 
		config->status = GCS_NOT_FOUND;
 
		return false;
 
	}
 

	
 
	if (config->filename == NULL) {
 
		const char *t = strrchr(config->full_path, PATHSEPCHAR);
 
		config->filename = strdup(t != NULL ? t + 1 : config->full_path);
 
	}
 

	
 
	/* 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;
 

	
 
	if (is_static) {
 
		/* Perform a 'safety scan' for static GRFs */
 
		LoadNewGRFFile(config, 62, GLS_SAFETYSCAN);
 

	
 
		/* GCF_UNSAFE is set if GLS_SAFETYSCAN finds unsafe actions */
 
		if (HASBIT(config->flags, GCF_UNSAFE)) return false;
 
	}
 

	
 
	return CalcGRFMD5Sum(config);
 
}
 

	
 

	
 
void ClearGRFConfig(GRFConfig **config)
 
{
 
	/* GCF_COPY as in NOT strdupped/alloced the filename, name and info */
 
	if (!HASBIT((*config)->flags, GCF_COPY)) {
 
		free((*config)->filename);
 
		free((*config)->full_path);
 
		free((*config)->name);
 
		free((*config)->info);
 
		free((*config)->error);
 

	
 
		if ((*config)->error != NULL) {
 
			free((*config)->error->custom_message);
 
			free((*config)->error->data);
 
			free((*config)->error);
 
		}
 
	}
 
	free(*config);
 
	*config = NULL;
 
}
 

	
 

	
 
/* Clear a GRF Config list */
 
void ClearGRFConfigList(GRFConfig **config)
 
{
 
	GRFConfig *c, *next;
 
	for (c = *config; c != NULL; c = next) {
 
		next = c->next;
 
		ClearGRFConfig(&c);
 
	}
 
	*config = NULL;
 
}
 

	
 

	
 
/** Copy a GRF Config list
 
 * @param dst pointer to destination list
 
 * @param src pointer to source list values
 
 * @return pointer to the last value added to the destination list */
 
GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src)
 
{
 
	/* Clear destination as it will be overwritten */
 
	ClearGRFConfigList(dst);
 
	for (; src != NULL; src = src->next) {
 
		GRFConfig *c = CallocT<GRFConfig>(1);
 
		*c = *src;
 
		if (src->filename  != NULL) c->filename  = strdup(src->filename);
 
		if (src->full_path != NULL) c->full_path = strdup(src->full_path);
 
		if (src->name      != NULL) c->name      = strdup(src->name);
 
		if (src->info      != NULL) c->info      = strdup(src->info);
 
		if (src->error     != NULL) {
 
			c->error = CallocT<GRFError>(1);
 
			memcpy(c->error, src->error, sizeof(GRFError));
 
			if (src->error->data != NULL) c->error->data = strdup(src->error->data);
 
			if (src->error->custom_message != NULL) c->error->custom_message = strdup(src->error->custom_message);
 
		}
 

	
 
		*dst = c;
 
		dst = &c->next;
 
	}
 

	
 
	return dst;
 
}
 

	
 
/**
 
 * Removes duplicates from lists of GRFConfigs. These duplicates
 
 * are introduced when the _grfconfig_static GRFs are appended
 
 * to the _grfconfig on a newgame or savegame. As the parameters
 
 * of the static GRFs could be different that the parameters of
 
 * the ones used non-statically. This can result in desyncs in
 
 * multiplayers, so the duplicate static GRFs have to be removed.
 
 *
 
 * This function _assumes_ that all static GRFs are placed after
 
 * the non-static GRFs.
 
 *
 
 * @param list the list to remove the duplicates from
 
 */
 
static void RemoveDuplicatesFromGRFConfigList(GRFConfig *list)
 
{
 
	GRFConfig *prev;
 
	GRFConfig *cur;
 

	
 
	if (list == NULL) return;
 

	
 
	for (prev = list, cur = list->next; cur != NULL; prev = cur, cur = cur->next) {
 
		if (cur->grfid != list->grfid) continue;
 

	
 
		prev->next = cur->next;
 
		ClearGRFConfig(&cur);
 
		cur = prev; // Just go back one so it continues as normal later on
 
	}
 

	
 
	RemoveDuplicatesFromGRFConfigList(list->next);
 
}
 

	
 
/**
 
 * Appends the static GRFs to a list of GRFs
 
 * @param dst the head of the list to add to
 
 */
 
void AppendStaticGRFConfigs(GRFConfig **dst)
 
{
 
	GRFConfig **tail = dst;
 
	while (*tail != NULL) tail = &(*tail)->next;
src/newgrf_config.h
Show inline comments
 
/* $Id$ */
 

	
 
/** @file newgrf_config.h */
 

	
 
#ifndef NEWGRF_CONFIG_H
 
#define NEWGRF_CONFIG_H
 

	
 
#include "openttd.h"
 

	
 
/* GRF config bit flags */
 
enum GCF_Flags {
 
	GCF_SYSTEM,    ///< GRF file is an openttd-internal system grf
 
	GCF_UNSAFE,    ///< GRF file is unsafe for static usage
 
	GCF_STATIC,    ///< GRF file is used statically (can be used in any MP game)
 
	GCF_COMPATIBLE,///< GRF file does not exactly match the requested GRF (different MD5SUM), but grfid matches)
 
	GCF_COPY,      ///< The data is copied from a grf in _all_grfs
 
};
 

	
 
enum GRFStatus {
 
	GCS_UNKNOWN,      ///< The status of this grf file is unknown
 
	GCS_DISABLED,     ///< GRF file is disabled
 
	GCS_NOT_FOUND,    ///< GRF file was not found in the local cache
 
	GCS_INITIALISED,  ///< GRF file has been initialised
 
	GCS_ACTIVATED     ///< GRF file has been activated
 
};
 

	
 
enum GRFListCompatibility{
 
	GLC_ALL_GOOD,
 
	GLC_COMPATIBLE,
 
	GLC_NOT_FOUND
 
};
 

	
 
struct GRFIdentifier {
 
	uint32 grfid;
 
	uint8 md5sum[16];
 
};
 

	
 
struct GRFError {
 
	char *custom_message;
 
	char *data;
 
	StringID message;
 
	StringID data;
 
	StringID severity;
 
	uint8 num_params;
 
	uint8 param_number[2];
 
};
 

	
 
struct GRFConfig : public GRFIdentifier {
 
	char *filename;
 
	char *full_path;
 
	char *name;
 
	char *info;
 
	GRFError *error;
 

	
 
	uint8 flags;
 
	GRFStatus status;
 
	uint32 param[0x80];
 
	uint8 num_params;
 

	
 
	struct GRFConfig *next;
 
};
 

	
 
/* 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;
 

	
 
/* First item in list of static GRF set up */
 
extern GRFConfig *_grfconfig_static;
 

	
 
void ScanNewGRFFiles();
 
const GRFConfig *FindGRFConfig(uint32 grfid, const uint8 *md5sum = NULL);
 
GRFConfig *GetGRFConfig(uint32 grfid);
 
GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src);
 
void AppendStaticGRFConfigs(GRFConfig **dst);
 
void AppendToGRFConfigList(GRFConfig **dst, GRFConfig *el);
 
void ClearGRFConfig(GRFConfig **config);
 
void ClearGRFConfigList(GRFConfig **config);
 
void ResetGRFConfig(bool defaults);
 
GRFListCompatibility IsGoodGRFConfigList();
 
bool FillGRFDetails(GRFConfig *config, bool is_static);
 
char *GRFBuildParamList(char *dst, const GRFConfig *c, const char *last);
 

	
 
/* In newgrf_gui.cpp */
 
void ShowNewGRFSettings(bool editable, bool show_params, bool exec_changes, GRFConfig **config);
 

	
src/newgrf_gui.cpp
Show inline comments
 
@@ -3,108 +3,108 @@
 
/** @file newgrf_gui.cpp */
 

	
 
#include "stdafx.h"
 
#include "openttd.h"
 
#include "functions.h"
 
#include "variables.h"
 
#include "gfx.h"
 
#include "gui.h"
 
#include "window.h"
 
#include "table/strings.h"
 
#include "table/sprites.h"
 
#include "newgrf.h"
 
#include "newgrf_config.h"
 
#include "strings.h"
 
#include "helpers.hpp"
 

	
 

	
 
/** Parse an integerlist string and set each found value
 
 * @param p the string to be parsed. Each element in the list is seperated by a
 
 * comma or a space character
 
 * @param items pointer to the integerlist-array that will be filled with values
 
 * @param maxitems the maximum number of elements the integerlist-array has
 
 * @return returns the number of items found, or -1 on an error */
 
static int parse_intlist(const char *p, int *items, int maxitems)
 
{
 
	int n = 0, v;
 
	char *end;
 

	
 
	for (;;) {
 
		v = strtol(p, &end, 0);
 
		if (p == end || n == maxitems) return -1;
 
		p = end;
 
		items[n++] = v;
 
		if (*p == '\0') break;
 
		if (*p != ',' && *p != ' ') return -1;
 
		p++;
 
	}
 

	
 
	return n;
 
}
 

	
 

	
 
static void ShowNewGRFInfo(const GRFConfig *c, uint x, uint y, uint w, uint bottom, bool show_params)
 
{
 
	char buff[256];
 

	
 
	if (c->error != NULL) {
 
		SetDParamStr(0, c->filename);
 
		SetDParam(1, c->error->data);
 
		SetDParamStr(1, c->error->data);
 
		for (uint i = 0; i < c->error->num_params; i++) {
 
			uint32 param = 0;
 
			byte param_number = c->error->param_number[i];
 

	
 
			if (param_number < c->num_params) param = c->param[param_number];
 

	
 
			SetDParam(2 + i, param);
 
		}
 

	
 
		char message[512];
 
		GetString(message, c->error->message, lastof(message));
 
		GetString(message, c->error->custom_message != NULL ? BindCString(c->error->custom_message) : c->error->message, lastof(message));
 

	
 
		SetDParamStr(0, message);
 
		y += DrawStringMultiLine(x, y, c->error->severity, w, bottom - y);
 
	}
 

	
 
	/* Draw filename or not if it is not known (GRF sent over internet) */
 
	if (c->filename != NULL) {
 
		SetDParamStr(0, c->filename);
 
		y += DrawStringMultiLine(x, y, STR_NEWGRF_FILENAME, w, bottom - y);
 
	}
 

	
 
	/* Prepare and draw GRF ID */
 
	snprintf(buff, lengthof(buff), "%08X", BSWAP32(c->grfid));
 
	SetDParamStr(0, buff);
 
	y += DrawStringMultiLine(x, y, STR_NEWGRF_GRF_ID, w, bottom - y);
 

	
 
	/* Prepare and draw MD5 sum */
 
	md5sumToString(buff, lastof(buff), c->md5sum);
 
	SetDParamStr(0, buff);
 
	y += DrawStringMultiLine(x, y, STR_NEWGRF_MD5SUM, w, bottom - y);
 

	
 
	/* Show GRF parameter list */
 
	if (show_params) {
 
		if (c->num_params > 0) {
 
			GRFBuildParamList(buff, c, lastof(buff));
 
			SetDParamStr(0, buff);
 
		} else {
 
			SetDParam(0, STR_01A9_NONE);
 
		}
 
		y += DrawStringMultiLine(x, y, STR_NEWGRF_PARAMETER, w, bottom - y);
 
	}
 

	
 
	/* Show flags */
 
	if (c->status == GCS_NOT_FOUND)        y += DrawStringMultiLine(x, y, STR_NEWGRF_NOT_FOUND, w, bottom - y);
 
	if (c->status == GCS_DISABLED)         y += DrawStringMultiLine(x, y, STR_NEWGRF_DISABLED, w, bottom - y);
 
	if (HASBIT(c->flags, GCF_COMPATIBLE)) y += DrawStringMultiLine(x, y, STR_NEWGRF_COMPATIBLE_LOADED, w, bottom - y);
 

	
 
	/* Draw GRF info if it exists */
 
	if (c->info != NULL && !StrEmpty(c->info)) {
 
		SetDParamStr(0, c->info);
 
		y += DrawStringMultiLine(x, y, STR_02BD, w, bottom - y);
 
	} else {
 
		y += DrawStringMultiLine(x, y, STR_NEWGRF_NO_INFO, w, bottom - y);
 
	}
 
}
 

	
 

	
 
/* Dialogue for adding NewGRF files to the selection */
src/newgrf_text.cpp
Show inline comments
 
@@ -400,70 +400,84 @@ char *GetGRFString(char *buff, uint16 st
 
	_last_grfid = _grf_text[stringid].grfid;
 

	
 
	/*Search the list of lang-strings of this stringid for current lang */
 
	for (search_text = _grf_text[stringid].textholder; search_text != NULL; search_text = search_text->next) {
 
		if (search_text->langid == _currentLangID) {
 
			return strecpy(buff, search_text->text, last);
 
		}
 

	
 
		/* If the current string is English or American, set it as the
 
		 * fallback language if the specific language isn't available. */
 
		if (search_text->langid == GRFLX_UNSPECIFIED || (default_text == NULL && (search_text->langid == GRFLX_ENGLISH || search_text->langid == GRFLX_AMERICAN))) {
 
			default_text = search_text;
 
		}
 
	}
 

	
 
	/* If there is a fallback string, return that */
 
	if (default_text != NULL) return strecpy(buff, default_text->text, last);
 

	
 
	/* Use the default string ID if the fallback string isn't available */
 
	return GetString(buff, _grf_text[stringid].def_string, last);
 
}
 

	
 
/**
 
 * Equivalence Setter function between game and newgrf langID.
 
 * This function will adjust _currentLangID as to what is the LangID
 
 * of the current language set by the user.
 
 * The array iso_codes will be used to find that match.
 
 * If not found, it will have to be standard english
 
 * This function is called after the user changed language,
 
 * from strings.cpp:ReadLanguagePack
 
 * @param iso_name iso code of current selection
 
 */
 
void SetCurrentGrfLangID(const char *iso_name)
 
{
 
	/* Use English by default, if we can't match up the iso_code. */
 
	byte ret = GRFLX_ENGLISH;
 
	byte i;
 

	
 
	for (i=0; i < lengthof(iso_codes); i++) {
 
		if (strncmp(iso_codes[i].code, iso_name, strlen(iso_codes[i].code)) == 0) {
 
			/* We found a match, so let's use it. */
 
			ret = i;
 
			break;
 
		}
 
	}
 
	_currentLangID = ret;
 
}
 

	
 
bool CheckGrfLangID(byte lang_id, byte grf_version)
 
{
 
	if (grf_version < 7) {
 
		switch (_currentLangID) {
 
			case GRFLX_GERMAN:  return (lang_id & GRFLB_GERMAN)  != 0;
 
			case GRFLX_FRENCH:  return (lang_id & GRFLB_FRENCH)  != 0;
 
			case GRFLX_SPANISH: return (lang_id & GRFLB_SPANISH) != 0;
 
			default:            return (lang_id & (GRFLB_ENGLISH | GRFLB_AMERICAN)) != 0;
 
		}
 
	}
 

	
 
	return (lang_id == _currentLangID || lang_id == GRFLX_UNSPECIFIED);
 
}
 

	
 
/**
 
 * House cleaning.
 
 * Remove all strings and reset the text counter.
 
 */
 
void CleanUpStrings()
 
{
 
	uint id;
 

	
 
	for (id = 0; id < _num_grf_texts; id++) {
 
		GRFText *grftext = _grf_text[id].textholder;
 
		while (grftext != NULL) {
 
			GRFText *grftext2 = grftext->next;
 
			delete grftext;
 
			grftext = grftext2;
 
		}
 
		_grf_text[id].grfid      = 0;
 
		_grf_text[id].stringid   = 0;
 
		_grf_text[id].textholder = NULL;
 
	}
 

	
 
	_num_grf_texts = 0;
 
}
src/newgrf_text.h
Show inline comments
 
/* $Id$ */
 
#ifndef NEWGRF_TEXT_H
 
#define NEWGRF_TEXT_H
 

	
 
/** @file newgrf_text.h
 
 * Header of Action 04 "universal holder" structure and functions
 
 */
 

	
 
StringID AddGRFString(uint32 grfid, uint16 stringid, byte langid, bool new_scheme, const char *text_to_add, StringID def_string);
 
StringID GetGRFStringID(uint32 grfid, uint16 stringid);
 
char *GetGRFString(char *buff, uint16 stringid, const char* last);
 
void CleanUpStrings();
 
void SetCurrentGrfLangID(const char *iso_name);
 
char *TranslateTTDPatchCodes(const char *str);
 

	
 
bool CheckGrfLangID(byte lang_id, byte grf_version);
 

	
 
#endif /* NEWGRF_TEXT_H */
0 comments (0 inline, 0 general)