summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpeter1138 <peter1138@openttd.org>2006-12-12 19:38:41 +0000
committerpeter1138 <peter1138@openttd.org>2006-12-12 19:38:41 +0000
commit08a494f184c20725f5cec8546c65854a8a667476 (patch)
tree574ad9deeac872fb0cbc50fb59447de01f6ff72c
parent2e9b97e3321aee8d6525d7e11eead2f67d30d0e8 (diff)
downloadopenttd-08a494f184c20725f5cec8546c65854a8a667476.tar.xz
(svn r7490) -Feature: Load a list of NewGRFs from the config (in the [newgrf-static] section) that should always be loaded. These will also be active during the intro screen, and in multiplayer games. Only "network-safe" NewGRFs are permitted, such as fonts and sprite replacement sets.
-rw-r--r--newgrf.c65
-rw-r--r--newgrf.h1
-rw-r--r--newgrf_config.c40
-rw-r--r--newgrf_config.h9
-rw-r--r--newgrf_gui.c2
-rw-r--r--settings.c75
6 files changed, 133 insertions, 59 deletions
diff --git a/newgrf.c b/newgrf.c
index ed757edf5..eb942a913 100644
--- a/newgrf.c
+++ b/newgrf.c
@@ -2471,8 +2471,8 @@ static void SkipIf(byte *buf, int len)
}
-/* Action 0x08 (GLS_FILESCAN) */
-static void ScanInfo(byte *buf, int len)
+/* Action 0x08 (GLS_SAFETYSCAN) */
+static void SafeInfo(byte *buf, int len)
{
uint8 version;
uint32 grfid;
@@ -2487,6 +2487,9 @@ static void ScanInfo(byte *buf, int len)
_cur_grfconfig->grfid = grfid;
+ /* GRF IDs starting with 0xFF are reserved for internal TTDPatch use */
+ if (GB(grfid, 24, 8) == 0xFF) SETBIT(_cur_grfconfig->flags, GCF_SYSTEM);
+
len -= 6;
name = (const char*)buf;
name_len = ttd_strnlen(name, len);
@@ -2502,7 +2505,14 @@ static void ScanInfo(byte *buf, int len)
_cur_grfconfig->info = TranslateTTDPatchCodes(info);
}
}
+}
+
+/* Action 0x08 (GLS_INFOSCAN) */
+static void ScanInfo(byte *buf, int len)
+{
+ SafeInfo(buf, len);
+ /* GLS_INFOSCAN only looks for the action 8, so we can skip the rest of the file */
_skip_sprites = -1;
}
@@ -3177,6 +3187,17 @@ static void GRFDataBlock(byte *buf, int len)
}
}
+
+/* Used during safety scan on unsafe actions */
+static void GRFUnsafe(byte *buf, int len)
+{
+ SETBIT(_cur_grfconfig->flags, GCF_UNSAFE);
+
+ /* Skip remainder of GRF if GRF ID is set */
+ if (_cur_grfconfig->grfid != 0) _skip_sprites = -1;
+}
+
+
static void InitializeGRFSpecial(void)
{
_ttdpatch_flags[0] = ((_patches.always_small_airport ? 1 : 0) << 0x0C) // keepsmallairport
@@ -3517,25 +3538,25 @@ static void DecodeSpecialSprite(uint num, GrfLoadingStage stage)
* 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, 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, },
+ /* 0x00 */ { NULL, GRFUnsafe, NULL, NULL, FeatureChangeInfo, },
+ /* 0x01 */ { NULL, GRFUnsafe, NULL, NULL, NewSpriteSet, },
+ /* 0x02 */ { NULL, GRFUnsafe, NULL, NULL, NewSpriteGroup, },
+ /* 0x03 */ { NULL, GRFUnsafe, NULL, NULL, FeatureMapSpriteGroup, },
+ /* 0x04 */ { NULL, NULL, NULL, NULL, FeatureNewName, },
+ /* 0x05 */ { NULL, NULL, NULL, NULL, GraphicsNew, },
+ /* 0x06 */ { NULL, NULL, NULL, CfgApply, CfgApply, },
+ /* 0x07 */ { NULL, NULL, NULL, NULL, SkipIf, },
+ /* 0x08 */ { ScanInfo, SafeInfo, NULL, GRFInfo, GRFInfo, },
+ /* 0x09 */ { NULL, NULL, NULL, SkipIf, SkipIf, },
+ /* 0x0A */ { NULL, NULL, NULL, NULL, SpriteReplace, },
+ /* 0x0B */ { NULL, NULL, NULL, GRFError, GRFError, },
+ /* 0x0C */ { NULL, NULL, NULL, GRFComment, GRFComment, },
+ /* 0x0D */ { NULL, GRFUnsafe, NULL, ParamSet, ParamSet, },
+ /* 0x0E */ { NULL, GRFUnsafe, NULL, GRFInhibit, GRFInhibit, },
+ /* 0x0F */ { NULL, NULL, NULL, NULL, NULL, },
+ /* 0x10 */ { NULL, NULL, DefineGotoLabel, NULL, NULL, },
+ /* 0x11 */ { NULL, GRFUnsafe, NULL, NULL, GRFSound, },
+ /* 0x12 */ { NULL, NULL, NULL, NULL, LoadFontGlyph, },
};
byte* buf;
@@ -3591,7 +3612,7 @@ void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage)
* 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_FILESCAN && stage != GLS_LABELSCAN) {
+ if (stage != GLS_FILESCAN && stage != GLS_SAFETYSCAN && stage != GLS_LABELSCAN) {
_cur_grffile = GetFileByFilename(filename);
if (_cur_grffile == NULL) error("File ``%s'' lost in cache.\n", filename);
if (stage == GLS_ACTIVATION && !HASBIT(config->flags, GCF_ACTIVATED)) return;
diff --git a/newgrf.h b/newgrf.h
index 77ed2f5bf..4d57ff4c9 100644
--- a/newgrf.h
+++ b/newgrf.h
@@ -8,6 +8,7 @@
typedef enum GrfLoadingStage {
GLS_FILESCAN,
+ GLS_SAFETYSCAN,
GLS_LABELSCAN,
GLS_INIT,
GLS_ACTIVATION,
diff --git a/newgrf_config.c b/newgrf_config.c
index ac7b60fd5..ef607c2b8 100644
--- a/newgrf_config.c
+++ b/newgrf_config.c
@@ -28,6 +28,7 @@
GRFConfig *_all_grfs;
GRFConfig *_grfconfig;
GRFConfig *_grfconfig_newgame;
+GRFConfig *_grfconfig_static;
/* Calculate the MD5 Sum for a GRF */
@@ -58,7 +59,7 @@ static bool CalcGRFMD5Sum(GRFConfig *config)
/* Find the GRFID and calculate the md5sum */
-bool FillGRFDetails(GRFConfig *config)
+bool FillGRFDetails(GRFConfig *config, bool is_static)
{
if (!FioCheckFileExists(config->filename)) {
SETBIT(config->flags, GCF_NOT_FOUND);
@@ -68,7 +69,10 @@ bool FillGRFDetails(GRFConfig *config)
/* 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);
+ LoadNewGRFFile(config, 62, is_static ? GLS_SAFETYSCAN : GLS_FILESCAN);
+
+ /* GCF_UNSAFE is set if GLS_SAFETYSCAN finds unsafe actions */
+ if (HASBIT(config->flags, GCF_UNSAFE)) return false;
/* Skip if the grfid is 0 (not read) or 0xFFFFFFFF (ttdp system grf) */
if (config->grfid == 0 || config->grfid == 0xFFFFFFFF) return false;
@@ -77,22 +81,28 @@ bool FillGRFDetails(GRFConfig *config)
}
+void ClearGRFConfig(GRFConfig *config)
+{
+ free(config->filename);
+ free(config->name);
+ free(config->info);
+ free(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);
+ ClearGRFConfig(c);
}
}
/* Copy a GRF Config list */
-static void CopyGRFConfigList(GRFConfig **dst, GRFConfig *src)
+static GRFConfig **CopyGRFConfigList(GRFConfig **dst, GRFConfig *src)
{
GRFConfig *c;
@@ -106,15 +116,21 @@ static void CopyGRFConfigList(GRFConfig **dst, GRFConfig *src)
*dst = c;
dst = &c->next;
}
+
+ return dst;
}
/* Reset the current GRF Config to either blank or newgame settings */
void ResetGRFConfig(bool defaults)
{
+ GRFConfig **c = &_grfconfig;
+
ClearGRFConfigList(_grfconfig);
_grfconfig = NULL;
- if (defaults) CopyGRFConfigList(&_grfconfig, _grfconfig_newgame);
+
+ if (defaults) c = CopyGRFConfigList(c, _grfconfig_newgame);
+ CopyGRFConfigList(c, _grfconfig_static);
}
@@ -138,7 +154,7 @@ bool IsGoodGRFConfigList(void)
res = false;
} else {
- DEBUG(grf, 1) ("[GRF] Loading GRF %X from %s", BSWAP32(c->grfid), f->filename);
+ DEBUG(grf, 1) ("[GRF] Loading GRF %08X from %s", BSWAP32(c->grfid), f->filename);
c->filename = strdup(f->filename);
c->name = strdup(f->name);
c->info = strdup(f->info);
@@ -186,7 +202,7 @@ static uint ScanPath(const char *path)
c = calloc(1, sizeof(*c));
c->filename = strdup(file);
- if (FillGRFDetails(c)) {
+ if (FillGRFDetails(c, false)) {
if (_all_grfs == NULL) {
_all_grfs = c;
} else {
@@ -294,6 +310,7 @@ static void Save_NGRF(void)
int index = 0;
for (c = _grfconfig; c != NULL; c = c->next) {
+ if (HASBIT(c->flags, GCF_STATIC)) continue;
SlSetArrayIndex(index++);
SlObject(c, _grfconfig_desc);
}
@@ -314,6 +331,9 @@ static void Load_NGRF(void)
last = &c->next;
}
+ /* Append static NewGRF configuration */
+ CopyGRFConfigList(last, _grfconfig_static);
+
ClearGRFConfigList(_grfconfig);
_grfconfig = first;
}
diff --git a/newgrf_config.h b/newgrf_config.h
index 45d0e270d..cb490ebad 100644
--- a/newgrf_config.h
+++ b/newgrf_config.h
@@ -8,6 +8,9 @@ enum {
GCF_DISABLED,
GCF_NOT_FOUND,
GCF_ACTIVATED,
+ GCF_SYSTEM,
+ GCF_UNSAFE,
+ GCF_STATIC,
};
typedef struct GRFConfig {
@@ -33,13 +36,17 @@ 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(void);
const GRFConfig *FindGRFConfig(uint32 grfid, uint8 *md5sum);
const GRFConfig *GetGRFConfig(uint32 grfid);
+void ClearGRFConfig(GRFConfig *config);
void ClearGRFConfigList(GRFConfig *config);
void ResetGRFConfig(bool defaults);
bool IsGoodGRFConfigList(void);
-bool FillGRFDetails(GRFConfig *config);
+bool FillGRFDetails(GRFConfig *config, bool is_static);
char *GRFBuildParamList(char *dst, const GRFConfig *c, const char *last);
/* In newgrf_gui.c */
diff --git a/newgrf_gui.c b/newgrf_gui.c
index c2e76a021..b31c0b177 100644
--- a/newgrf_gui.c
+++ b/newgrf_gui.c
@@ -274,6 +274,8 @@ static void NewGRFWndProc(Window *w, WindowEvent *e)
/* Pick a colour */
if (HASBIT(c->flags, GCF_NOT_FOUND) || HASBIT(c->flags, GCF_DISABLED)) {
pal = PALETTE_TO_RED;
+ } else if (HASBIT(c->flags, GCF_STATIC)) {
+ pal = PALETTE_TO_YELLOW;
} else if (HASBIT(c->flags, GCF_ACTIVATED)) {
pal = PALETTE_TO_GREEN;
} else {
diff --git a/settings.c b/settings.c
index ee1f8e675..498f5d2f1 100644
--- a/settings.c
+++ b/settings.c
@@ -1495,41 +1495,62 @@ static const SettingDesc _currency_settings[] = {
#undef NO
#undef CR
-static const char *GRFProcessParams(const IniItem *item, uint index)
+
+/* Load a GRF configuration from the given group name */
+static GRFConfig *GRFLoadConfig(IniFile *ini, const char *grpname, bool is_static)
{
- GRFConfig *c;
+ IniGroup *group = ini_getgroup(ini, grpname, -1);
+ IniItem *item;
+ GRFConfig *first = NULL;
+ GRFConfig **curr = &first;
- /* Saving newgrf stuff to configuration, not done since it is kept the same */
- if (item == NULL) return NULL;
+ if (group == NULL) return NULL;
- /* Loading newgrf stuff from configuration file */
- c = calloc(1, sizeof(*c));
- c->filename = strdup(item->name);
- if (!FillGRFDetails(c)) {
- ShowInfoF("ini: ignoring invalid NewGRF '%s'", c->filename);
- return NULL;
- }
+ for (item = group->item; item != NULL; item = item->next) {
+ GRFConfig *c = calloc(1, sizeof(*c));
+ c->filename = strdup(item->name);
- if (*item->value != '\0') {
- 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;
+ /* Parse parameters */
+ if (*item->value != '\0') {
+ 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 (_grfconfig_newgame == NULL) {
- _grfconfig_newgame = c;
- } else {
- GRFConfig *c2;
- /* Attach the label to the end of the list */
- for (c2 = _grfconfig_newgame; c2->next != NULL; c2 = c2->next);
- c2->next = c;
+ /* Check if item is valid */
+ if (!FillGRFDetails(c, is_static)) {
+ const char *msg;
+
+ if (HASBIT(c->flags, GCF_NOT_FOUND)) {
+ msg = "not found";
+ } else if (HASBIT(c->flags, GCF_UNSAFE)) {
+ msg = "unsafe for static use";
+ } else if (HASBIT(c->flags, GCF_SYSTEM)) {
+ msg = "system NewGRF";
+ } else {
+ msg = "unknown";
+ }
+
+ ShowInfoF("ini: ignoring invalid NewGRF '%s': %s", item->name, msg);
+ ClearGRFConfig(c);
+ continue;
+ }
+
+ /* Mark file as static to avoid saving in savegame. */
+ if (is_static) SETBIT(c->flags, GCF_STATIC);
+
+ /* Add item to list */
+ *curr = c;
+ curr = &c->next;
}
- return c->filename;
+ return first;
}
+
+/* Save a GRF configuration to the given group name */
static void GRFSaveConfig(IniFile *ini, const char *grpname, const GRFConfig *list)
{
IniGroup *group = ini_getgroup(ini, grpname, -1);
@@ -1575,7 +1596,8 @@ void LoadFromConfig(void)
{
IniFile *ini = ini_load(_config_file);
HandleSettingDescs(ini, ini_load_settings, ini_load_setting_list);
- ini_load_setting_list(ini, "newgrf", NULL, 0, GRFProcessParams);
+ _grfconfig_newgame = GRFLoadConfig(ini, "newgrf", false);
+ _grfconfig_static = GRFLoadConfig(ini, "newgrf-static", true);
ini_free(ini);
}
@@ -1585,6 +1607,7 @@ void SaveToConfig(void)
IniFile *ini = ini_load(_config_file);
HandleSettingDescs(ini, ini_save_settings, ini_save_setting_list);
GRFSaveConfig(ini, "newgrf", _grfconfig_newgame);
+ GRFSaveConfig(ini, "newgrf-static", _grfconfig_static);
ini_save(_config_file, ini);
ini_free(ini);
}