Changeset - r18007:5ef6f0cf0861
[Not reviewed]
master
0 5 0
rubidium - 13 years ago 2011-08-24 13:48:29
rubidium@openttd.org
(svn r22826) -Codechange: pass sub directory to NewGRF loading functions
5 files changed with 31 insertions and 14 deletions:
0 comments (0 inline, 0 general)
src/gfxinit.cpp
Show inline comments
 
@@ -171,25 +171,25 @@ static void LoadSpriteTables()
 
	GRFConfig *top = _grfconfig;
 
	GRFConfig *master = new GRFConfig(used_set->files[GFT_EXTRA].filename);
 

	
 
	/* We know the palette of the base set, so if the base NewGRF is not
 
	 * setting one, use the palette of the base set and not the global
 
	 * one which might be the wrong palette for this base NewGRF.
 
	 * The value set here might be overridden via action14 later. */
 
	switch (used_set->palette) {
 
		case PAL_DOS:     master->palette |= GRFP_GRF_DOS;     break;
 
		case PAL_WINDOWS: master->palette |= GRFP_GRF_WINDOWS; break;
 
		default: break;
 
	}
 
	FillGRFDetails(master, false);
 
	FillGRFDetails(master, false, BASESET_DIR);
 

	
 
	ClrBit(master->flags, GCF_INIT_ONLY);
 
	master->next = top;
 
	_grfconfig = master;
 

	
 
	LoadNewGRF(SPR_NEWGRFS_BASE, i);
 

	
 
	/* Free and remove the top element. */
 
	delete master;
 
	_grfconfig = top;
 
}
 

	
src/newgrf.cpp
Show inline comments
 
@@ -8067,25 +8067,32 @@ static void DecodeSpecialSprite(byte *bu
 
			grfmsg(7, "DecodeSpecialSprite: Skipping action 0x%02X in stage %d", action, stage);
 
		} else {
 
			grfmsg(7, "DecodeSpecialSprite: Handling action 0x%02X in stage %d", action, stage);
 
			handlers[action][stage](bufp);
 
		}
 
	} catch (...) {
 
		grfmsg(1, "DecodeSpecialSprite: Tried to read past end of pseudo-sprite data");
 
		DisableGrf(STR_NEWGRF_ERROR_READ_BOUNDS);
 
	}
 
}
 

	
 

	
 
void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage)
 
/**
 
 * Load a particular NewGRF.
 
 * @param config     The configuration of the to be loaded NewGRF.
 
 * @param file_index The Fio index of the first NewGRF to load.
 
 * @param stage      The loading stage of the NewGRF.
 
 * @param subdir     The sub directory to find the NewGRF in.
 
 */
 
void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, Subdirectory subdir)
 
{
 
	const char *filename = config->filename;
 
	uint16 num;
 

	
 
	/* A .grf file is activated only if it was active when the game was
 
	 * started.  If a game is loaded, only its active .grfs will be
 
	 * reactivated, unless "loadallgraphics on" is used.  A .grf file is
 
	 * considered active if its action 8 has been processed, i.e. its
 
	 * action 8 hasn't been skipped using an action 7.
 
	 *
 
	 * 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
 
@@ -8096,25 +8103,25 @@ void LoadNewGRFFile(GRFConfig *config, u
 
		if (stage == GLS_RESERVE && config->status != GCS_INITIALISED) return;
 
		if (stage == GLS_ACTIVATION && !HasBit(config->flags, GCF_RESERVED)) return;
 
		_cur.grffile->is_ottdfile = config->IsOpenTTDBaseGRF();
 
	}
 

	
 
	if (file_index > LAST_GRF_SLOT) {
 
		DEBUG(grf, 0, "'%s' is not loaded as the maximum number of GRFs has been reached", filename);
 
		config->status = GCS_DISABLED;
 
		config->error  = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED);
 
		return;
 
	}
 

	
 
	FioOpenFile(file_index, filename, NEWGRF_DIR);
 
	FioOpenFile(file_index, filename, subdir);
 
	_cur.file_index = file_index; // XXX
 
	_palette_remap_grf[_cur.file_index] = (config->palette & GRFP_USE_MASK);
 

	
 
	_cur.grfconfig = config;
 

	
 
	DEBUG(grf, 2, "LoadNewGRFFile: Reading NewGRF-file '%s'", filename);
 

	
 
	/* Skip the first sprite; we don't care about how many sprites this
 
	 * does contain; newest TTDPatches and George's longvehicles don't
 
	 * neither, apparently. */
 
	if (FioReadWord() == 4 && FioReadByte() == 0xFF) {
 
		FioReadDword();
 
@@ -8395,24 +8402,29 @@ static void AfterLoadGRFs()
 
		}
 
	}
 

	
 
	SetYearEngineAgingStops();
 

	
 
	FinalisePriceBaseMultipliers();
 

	
 
	/* Deallocate temporary loading data */
 
	free(_gted);
 
	_grm_sprites.clear();
 
}
 

	
 
/**
 
 * Load all the NewGRFs.
 
 * @param load_index The offset for the first sprite to add.
 
 * @param file_index The Fio index of the first NewGRF to load.
 
 */
 
void LoadNewGRF(uint load_index, uint file_index)
 
{
 
	/* In case of networking we need to "sync" the start values
 
	 * so all NewGRFs are loaded equally. For this we use the
 
	 * start date of the game and we set the counters, etc. to
 
	 * 0 so they're the same too. */
 
	Date date            = _date;
 
	Year year            = _cur_year;
 
	DateFract date_fract = _date_fract;
 
	uint16 tick_counter  = _tick_counter;
 
	byte display_opt     = _display_opt;
 

	
 
@@ -8449,32 +8461,33 @@ void LoadNewGRF(uint load_index, uint fi
 
		 * This ensures that action7/9 conditions 0x06 - 0x0A work correctly. */
 
		for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
 
			if (c->status == GCS_ACTIVATED) c->status = GCS_INITIALISED;
 
		}
 

	
 
		uint slot = file_index;
 

	
 
		_cur.stage = stage;
 
		for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
 
			if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND) continue;
 
			if (stage > GLS_INIT && HasBit(c->flags, GCF_INIT_ONLY)) continue;
 

	
 
			if (!FioCheckFileExists(c->filename)) {
 
			Subdirectory subdir = slot == file_index ? BASESET_DIR : NEWGRF_DIR;
 
			if (!FioCheckFileExists(c->filename, subdir)) {
 
				DEBUG(grf, 0, "NewGRF file is missing '%s'; disabling", c->filename);
 
				c->status = GCS_NOT_FOUND;
 
				continue;
 
			}
 

	
 
			if (stage == GLS_LABELSCAN) InitNewGRFFile(c);
 
			LoadNewGRFFile(c, slot++, stage);
 
			LoadNewGRFFile(c, slot++, stage, subdir);
 
			if (stage == GLS_RESERVE) {
 
				SetBit(c->flags, GCF_RESERVED);
 
			} else if (stage == GLS_ACTIVATION) {
 
				ClrBit(c->flags, GCF_RESERVED);
 
				assert(GetFileByGRFID(c->ident.grfid) == _cur.grffile);
 
				ClearTemporaryNewGRFData(_cur.grffile);
 
				BuildCargoTranslationMap();
 
				DEBUG(sprite, 2, "LoadNewGRF: Currently %i sprites are loaded", _cur.spriteid);
 
			} else if (stage == GLS_INIT && HasBit(c->flags, GCF_INIT_ONLY)) {
 
				/* We're not going to activate this, so free whatever data we allocated */
 
				ClearTemporaryNewGRFData(_cur.grffile);
 
			}
src/newgrf.h
Show inline comments
 
@@ -5,24 +5,25 @@
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file newgrf.h Base for the NewGRF implementation. */
 

	
 
#ifndef NEWGRF_H
 
#define NEWGRF_H
 

	
 
#include "cargotype.h"
 
#include "rail_type.h"
 
#include "fileio_type.h"
 

	
 
enum GrfLoadingStage {
 
	GLS_FILESCAN,
 
	GLS_SAFETYSCAN,
 
	GLS_LABELSCAN,
 
	GLS_INIT,
 
	GLS_RESERVE,
 
	GLS_ACTIVATION,
 
	GLS_END,
 
};
 

	
 
DECLARE_POSTFIX_INCREMENT(GrfLoadingStage)
 
@@ -130,25 +131,25 @@ enum ShoreReplacement {
 

	
 
struct GRFLoadedFeatures {
 
	bool has_2CC;             ///< Set if any vehicle is loaded which uses 2cc (two company colours).
 
	uint64 used_liveries;     ///< Bitmask of #LiveryScheme used by the defined engines.
 
	bool has_newhouses;       ///< Set if there are any newhouses loaded.
 
	bool has_newindustries;   ///< Set if there are any newindustries loaded.
 
	ShoreReplacement shore;   ///< It which way shore sprites were replaced.
 
};
 

	
 
/* Indicates which are the newgrf features currently loaded ingame */
 
extern GRFLoadedFeatures _loaded_newgrf_features;
 

	
 
void LoadNewGRFFile(struct GRFConfig *config, uint file_index, GrfLoadingStage stage);
 
void LoadNewGRFFile(struct GRFConfig *config, uint file_index, GrfLoadingStage stage, Subdirectory subdir);
 
void LoadNewGRF(uint load_index, uint file_index);
 
void ReloadNewGRFData(); // in saveload/afterload.cpp
 
void ResetNewGRFData();
 
void ResetPersistentNewGRFData();
 

	
 
void CDECL grfmsg(int severity, const char *str, ...) WARN_FORMAT(2, 3);
 

	
 
bool HasGrfMiscBit(GrfMiscBit bit);
 
bool GetGlobalVariable(byte param, uint32 *value);
 

	
 
StringID MapGRFStringID(uint32 grfid, StringID str);
 
void ShowNewGRFError();
src/newgrf_config.cpp
Show inline comments
 
@@ -273,79 +273,81 @@ void GRFParameterInfo::SetValue(struct G
 
 */
 
bool UpdateNewGRFConfigPalette(int32 p1)
 
{
 
	for (GRFConfig *c = _grfconfig_newgame; c != NULL; c = c->next) c->SetSuitablePalette();
 
	for (GRFConfig *c = _grfconfig_static;  c != NULL; c = c->next) c->SetSuitablePalette();
 
	for (GRFConfig *c = _all_grfs;          c != NULL; c = c->next) c->SetSuitablePalette();
 
	return true;
 
}
 

	
 
/**
 
 * Calculate the MD5 sum for a GRF, and store it in the config.
 
 * @param config GRF to compute.
 
 * @param subdir The subdirectory to look in.
 
 * @return MD5 sum was successfully computed
 
 */
 
static bool CalcGRFMD5Sum(GRFConfig *config)
 
static bool CalcGRFMD5Sum(GRFConfig *config, Subdirectory subdir)
 
{
 
	FILE *f;
 
	Md5 checksum;
 
	uint8 buffer[1024];
 
	size_t len, size;
 

	
 
	/* open the file */
 
	f = FioFOpenFile(config->filename, "rb", NEWGRF_DIR, &size);
 
	f = FioFOpenFile(config->filename, "rb", subdir, &size);
 
	if (f == NULL) return false;
 

	
 
	/* calculate md5sum */
 
	while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, f)) != 0 && size != 0) {
 
		size -= len;
 
		checksum.Append(buffer, len);
 
	}
 
	checksum.Finish(config->ident.md5sum);
 

	
 
	FioFCloseFile(f);
 

	
 
	return true;
 
}
 

	
 

	
 
/**
 
 * Find the GRFID of a given grf, and calculate its md5sum.
 
 * @param config    grf to fill.
 
 * @param is_static grf is static.
 
 * @param subdir    the subdirectory to search in.
 
 * @return Operation was successfully completed.
 
 */
 
bool FillGRFDetails(GRFConfig *config, bool is_static)
 
bool FillGRFDetails(GRFConfig *config, bool is_static, Subdirectory subdir)
 
{
 
	if (!FioCheckFileExists(config->filename)) {
 
	if (!FioCheckFileExists(config->filename, subdir)) {
 
		config->status = GCS_NOT_FOUND;
 
		return false;
 
	}
 

	
 
	/* Find and load the Action 8 information */
 
	LoadNewGRFFile(config, CONFIG_SLOT, GLS_FILESCAN);
 
	LoadNewGRFFile(config, CONFIG_SLOT, GLS_FILESCAN, subdir);
 
	config->SetSuitablePalette();
 

	
 
	/* Skip if the grfid is 0 (not read) or 0xFFFFFFFF (ttdp system grf) */
 
	if (config->ident.grfid == 0 || config->ident.grfid == 0xFFFFFFFF || config->IsOpenTTDBaseGRF()) return false;
 

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

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

	
 
	return CalcGRFMD5Sum(config);
 
	return CalcGRFMD5Sum(config, subdir);
 
}
 

	
 

	
 
/**
 
 * Clear a GRF Config list, freeing all nodes.
 
 * @param config Start of the list.
 
 * @post \a config is set to \c NULL.
 
 */
 
void ClearGRFConfigList(GRFConfig **config)
 
{
 
	GRFConfig *c, *next;
 
	for (c = *config; c != NULL; c = next) {
src/newgrf_config.h
Show inline comments
 
@@ -7,24 +7,25 @@
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file newgrf_config.h Functions to find and configure NewGRFs. */
 

	
 
#ifndef NEWGRF_CONFIG_H
 
#define NEWGRF_CONFIG_H
 

	
 
#include "strings_type.h"
 
#include "core/alloc_type.hpp"
 
#include "core/smallmap_type.hpp"
 
#include "misc/countedptr.hpp"
 
#include "fileio_type.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
 
	GCF_INIT_ONLY,  ///< GRF file is processed up to GLS_INIT
 
	GCF_RESERVED,   ///< GRF file passed GLS_RESERVE stage
 
	GCF_INVALID,    ///< GRF is unusable with this version of OpenTTD
 
};
 
@@ -197,25 +198,25 @@ struct NewGRFScanCallback {
 
};
 

	
 
void ScanNewGRFFiles(NewGRFScanCallback *callback);
 
void CheckForMissingSprites();
 
const GRFConfig *FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8 *md5sum = NULL, uint32 desired_version = 0);
 
GRFConfig *GetGRFConfig(uint32 grfid, uint32 mask = 0xFFFFFFFF);
 
GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src, bool init_only);
 
void AppendStaticGRFConfigs(GRFConfig **dst);
 
void AppendToGRFConfigList(GRFConfig **dst, GRFConfig *el);
 
void ClearGRFConfigList(GRFConfig **config);
 
void ResetGRFConfig(bool defaults);
 
GRFListCompatibility IsGoodGRFConfigList(GRFConfig *grfconfig);
 
bool FillGRFDetails(GRFConfig *config, bool is_static);
 
bool FillGRFDetails(GRFConfig *config, bool is_static, Subdirectory subdir = NEWGRF_DIR);
 
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);
 

	
 
#ifdef ENABLE_NETWORK
 
/** For communication about GRFs over the network */
 
#define UNKNOWN_GRF_NAME_PLACEHOLDER "<Unknown>"
 
GRFTextWrapper *FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create);
 
#endif /* ENABLE_NETWORK */
 

	
 
void UpdateNewGRFScanStatus(uint num, const char *name);
0 comments (0 inline, 0 general)