(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.

pull/155/head
peter1138 18 years ago
parent 2e9b97e332
commit 08a494f184

@ -2471,8 +2471,8 @@ static void SkipIf(byte *buf, int len)
} }
/* Action 0x08 (GLS_FILESCAN) */ /* Action 0x08 (GLS_SAFETYSCAN) */
static void ScanInfo(byte *buf, int len) static void SafeInfo(byte *buf, int len)
{ {
uint8 version; uint8 version;
uint32 grfid; uint32 grfid;
@ -2487,6 +2487,9 @@ static void ScanInfo(byte *buf, int len)
_cur_grfconfig->grfid = grfid; _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; len -= 6;
name = (const char*)buf; name = (const char*)buf;
name_len = ttd_strnlen(name, len); name_len = ttd_strnlen(name, len);
@ -2502,7 +2505,14 @@ static void ScanInfo(byte *buf, int len)
_cur_grfconfig->info = TranslateTTDPatchCodes(info); _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; _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) static void InitializeGRFSpecial(void)
{ {
_ttdpatch_flags[0] = ((_patches.always_small_airport ? 1 : 0) << 0x0C) // keepsmallairport _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. * 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. */ * In other stages we skip action 0x10 since it's already dealt with. */
static const SpecialSpriteHandler handlers[][GLS_END] = { static const SpecialSpriteHandler handlers[][GLS_END] = {
/* 0x00 */ { NULL, NULL, NULL, FeatureChangeInfo, }, /* 0x00 */ { NULL, GRFUnsafe, NULL, NULL, FeatureChangeInfo, },
/* 0x01 */ { NULL, NULL, NULL, NewSpriteSet, }, /* 0x01 */ { NULL, GRFUnsafe, NULL, NULL, NewSpriteSet, },
/* 0x02 */ { NULL, NULL, NULL, NewSpriteGroup, }, /* 0x02 */ { NULL, GRFUnsafe, NULL, NULL, NewSpriteGroup, },
/* 0x03 */ { NULL, NULL, NULL, FeatureMapSpriteGroup, }, /* 0x03 */ { NULL, GRFUnsafe, NULL, NULL, FeatureMapSpriteGroup, },
/* 0x04 */ { NULL, NULL, NULL, FeatureNewName, }, /* 0x04 */ { NULL, NULL, NULL, NULL, FeatureNewName, },
/* 0x05 */ { NULL, NULL, NULL, GraphicsNew, }, /* 0x05 */ { NULL, NULL, NULL, NULL, GraphicsNew, },
/* 0x06 */ { NULL, NULL, CfgApply, CfgApply, }, /* 0x06 */ { NULL, NULL, NULL, CfgApply, CfgApply, },
/* 0x07 */ { NULL, NULL, NULL, SkipIf, }, /* 0x07 */ { NULL, NULL, NULL, NULL, SkipIf, },
/* 0x08 */ { ScanInfo, NULL, GRFInfo, GRFInfo, }, /* 0x08 */ { ScanInfo, SafeInfo, NULL, GRFInfo, GRFInfo, },
/* 0x09 */ { NULL, NULL, SkipIf, SkipIf, }, /* 0x09 */ { NULL, NULL, NULL, SkipIf, SkipIf, },
/* 0x0A */ { NULL, NULL, NULL, SpriteReplace, }, /* 0x0A */ { NULL, NULL, NULL, NULL, SpriteReplace, },
/* 0x0B */ { NULL, NULL, GRFError, GRFError, }, /* 0x0B */ { NULL, NULL, NULL, GRFError, GRFError, },
/* 0x0C */ { NULL, NULL, GRFComment, GRFComment, }, /* 0x0C */ { NULL, NULL, NULL, GRFComment, GRFComment, },
/* 0x0D */ { NULL, NULL, ParamSet, ParamSet, }, /* 0x0D */ { NULL, GRFUnsafe, NULL, ParamSet, ParamSet, },
/* 0x0E */ { NULL, NULL, GRFInhibit, GRFInhibit, }, /* 0x0E */ { NULL, GRFUnsafe, NULL, GRFInhibit, GRFInhibit, },
/* 0x0F */ { NULL, NULL, NULL, NULL, }, /* 0x0F */ { NULL, NULL, NULL, NULL, NULL, },
/* 0x10 */ { NULL, DefineGotoLabel, NULL, NULL, }, /* 0x10 */ { NULL, NULL, DefineGotoLabel, NULL, NULL, },
/* 0x11 */ { NULL, NULL, NULL, GRFSound, }, /* 0x11 */ { NULL, GRFUnsafe, NULL, NULL, GRFSound, },
/* 0x12 */ { NULL, NULL, NULL, LoadFontGlyph, }, /* 0x12 */ { NULL, NULL, NULL, NULL, LoadFontGlyph, },
}; };
byte* buf; 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 * 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 * carried out. All others are ignored, because they only need to be
* processed once at initialization. */ * 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); _cur_grffile = GetFileByFilename(filename);
if (_cur_grffile == NULL) error("File ``%s'' lost in cache.\n", filename); if (_cur_grffile == NULL) error("File ``%s'' lost in cache.\n", filename);
if (stage == GLS_ACTIVATION && !HASBIT(config->flags, GCF_ACTIVATED)) return; if (stage == GLS_ACTIVATION && !HASBIT(config->flags, GCF_ACTIVATED)) return;

@ -8,6 +8,7 @@
typedef enum GrfLoadingStage { typedef enum GrfLoadingStage {
GLS_FILESCAN, GLS_FILESCAN,
GLS_SAFETYSCAN,
GLS_LABELSCAN, GLS_LABELSCAN,
GLS_INIT, GLS_INIT,
GLS_ACTIVATION, GLS_ACTIVATION,

@ -28,6 +28,7 @@
GRFConfig *_all_grfs; GRFConfig *_all_grfs;
GRFConfig *_grfconfig; GRFConfig *_grfconfig;
GRFConfig *_grfconfig_newgame; GRFConfig *_grfconfig_newgame;
GRFConfig *_grfconfig_static;
/* Calculate the MD5 Sum for a GRF */ /* Calculate the MD5 Sum for a GRF */
@ -58,7 +59,7 @@ static bool CalcGRFMD5Sum(GRFConfig *config)
/* Find the GRFID and calculate the md5sum */ /* Find the GRFID and calculate the md5sum */
bool FillGRFDetails(GRFConfig *config) bool FillGRFDetails(GRFConfig *config, bool is_static)
{ {
if (!FioCheckFileExists(config->filename)) { if (!FioCheckFileExists(config->filename)) {
SETBIT(config->flags, GCF_NOT_FOUND); SETBIT(config->flags, GCF_NOT_FOUND);
@ -68,7 +69,10 @@ bool FillGRFDetails(GRFConfig *config)
/* Find and load the Action 8 information */ /* Find and load the Action 8 information */
/* 62 is the last file slot before sample.cat. /* 62 is the last file slot before sample.cat.
* Should perhaps be some "don't care" value */ * 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) */ /* Skip if the grfid is 0 (not read) or 0xFFFFFFFF (ttdp system grf) */
if (config->grfid == 0 || config->grfid == 0xFFFFFFFF) return false; 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 */ /* Clear a GRF Config list */
void ClearGRFConfigList(GRFConfig *config) void ClearGRFConfigList(GRFConfig *config)
{ {
GRFConfig *c, *next; GRFConfig *c, *next;
for (c = config; c != NULL; c = next) { for (c = config; c != NULL; c = next) {
next = c->next; next = c->next;
free(c->filename); ClearGRFConfig(c);
free(c->name);
free(c->info);
free(c);
} }
} }
/* Copy a GRF Config list */ /* Copy a GRF Config list */
static void CopyGRFConfigList(GRFConfig **dst, GRFConfig *src) static GRFConfig **CopyGRFConfigList(GRFConfig **dst, GRFConfig *src)
{ {
GRFConfig *c; GRFConfig *c;
@ -106,15 +116,21 @@ static void CopyGRFConfigList(GRFConfig **dst, GRFConfig *src)
*dst = c; *dst = c;
dst = &c->next; dst = &c->next;
} }
return dst;
} }
/* Reset the current GRF Config to either blank or newgame settings */ /* Reset the current GRF Config to either blank or newgame settings */
void ResetGRFConfig(bool defaults) void ResetGRFConfig(bool defaults)
{ {
GRFConfig **c = &_grfconfig;
ClearGRFConfigList(_grfconfig); ClearGRFConfigList(_grfconfig);
_grfconfig = NULL; _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; res = false;
} else { } 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->filename = strdup(f->filename);
c->name = strdup(f->name); c->name = strdup(f->name);
c->info = strdup(f->info); c->info = strdup(f->info);
@ -186,7 +202,7 @@ static uint ScanPath(const char *path)
c = calloc(1, sizeof(*c)); c = calloc(1, sizeof(*c));
c->filename = strdup(file); c->filename = strdup(file);
if (FillGRFDetails(c)) { if (FillGRFDetails(c, false)) {
if (_all_grfs == NULL) { if (_all_grfs == NULL) {
_all_grfs = c; _all_grfs = c;
} else { } else {
@ -294,6 +310,7 @@ static void Save_NGRF(void)
int index = 0; int index = 0;
for (c = _grfconfig; c != NULL; c = c->next) { for (c = _grfconfig; c != NULL; c = c->next) {
if (HASBIT(c->flags, GCF_STATIC)) continue;
SlSetArrayIndex(index++); SlSetArrayIndex(index++);
SlObject(c, _grfconfig_desc); SlObject(c, _grfconfig_desc);
} }
@ -314,6 +331,9 @@ static void Load_NGRF(void)
last = &c->next; last = &c->next;
} }
/* Append static NewGRF configuration */
CopyGRFConfigList(last, _grfconfig_static);
ClearGRFConfigList(_grfconfig); ClearGRFConfigList(_grfconfig);
_grfconfig = first; _grfconfig = first;
} }

@ -8,6 +8,9 @@ enum {
GCF_DISABLED, GCF_DISABLED,
GCF_NOT_FOUND, GCF_NOT_FOUND,
GCF_ACTIVATED, GCF_ACTIVATED,
GCF_SYSTEM,
GCF_UNSAFE,
GCF_STATIC,
}; };
typedef struct GRFConfig { typedef struct GRFConfig {
@ -33,13 +36,17 @@ extern GRFConfig *_grfconfig;
/* First item in list of default GRF set up */ /* First item in list of default GRF set up */
extern GRFConfig *_grfconfig_newgame; extern GRFConfig *_grfconfig_newgame;
/* First item in list of static GRF set up */
extern GRFConfig *_grfconfig_static;
void ScanNewGRFFiles(void); void ScanNewGRFFiles(void);
const GRFConfig *FindGRFConfig(uint32 grfid, uint8 *md5sum); const GRFConfig *FindGRFConfig(uint32 grfid, uint8 *md5sum);
const GRFConfig *GetGRFConfig(uint32 grfid); const GRFConfig *GetGRFConfig(uint32 grfid);
void ClearGRFConfig(GRFConfig *config);
void ClearGRFConfigList(GRFConfig *config); void ClearGRFConfigList(GRFConfig *config);
void ResetGRFConfig(bool defaults); void ResetGRFConfig(bool defaults);
bool IsGoodGRFConfigList(void); bool IsGoodGRFConfigList(void);
bool FillGRFDetails(GRFConfig *config); bool FillGRFDetails(GRFConfig *config, bool is_static);
char *GRFBuildParamList(char *dst, const GRFConfig *c, const char *last); char *GRFBuildParamList(char *dst, const GRFConfig *c, const char *last);
/* In newgrf_gui.c */ /* In newgrf_gui.c */

@ -274,6 +274,8 @@ static void NewGRFWndProc(Window *w, WindowEvent *e)
/* Pick a colour */ /* Pick a colour */
if (HASBIT(c->flags, GCF_NOT_FOUND) || HASBIT(c->flags, GCF_DISABLED)) { if (HASBIT(c->flags, GCF_NOT_FOUND) || HASBIT(c->flags, GCF_DISABLED)) {
pal = PALETTE_TO_RED; pal = PALETTE_TO_RED;
} else if (HASBIT(c->flags, GCF_STATIC)) {
pal = PALETTE_TO_YELLOW;
} else if (HASBIT(c->flags, GCF_ACTIVATED)) { } else if (HASBIT(c->flags, GCF_ACTIVATED)) {
pal = PALETTE_TO_GREEN; pal = PALETTE_TO_GREEN;
} else { } else {

@ -1495,41 +1495,62 @@ static const SettingDesc _currency_settings[] = {
#undef NO #undef NO
#undef CR #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 (group == NULL) return NULL;
if (item == NULL) return NULL;
/* Loading newgrf stuff from configuration file */ for (item = group->item; item != NULL; item = item->next) {
c = calloc(1, sizeof(*c)); GRFConfig *c = calloc(1, sizeof(*c));
c->filename = strdup(item->name); c->filename = strdup(item->name);
if (!FillGRFDetails(c)) {
ShowInfoF("ini: ignoring invalid NewGRF '%s'", c->filename);
return NULL;
}
if (*item->value != '\0') { /* Parse parameters */
c->num_params = parse_intlist(item->value, (int*)c->param, lengthof(c->param)); if (*item->value != '\0') {
if (c->num_params == (byte)-1) { c->num_params = parse_intlist(item->value, (int*)c->param, lengthof(c->param));
ShowInfoF("ini: error in array '%s'", item->name); if (c->num_params == (byte)-1) {
c->num_params = 0; ShowInfoF("ini: error in array '%s'", item->name);
c->num_params = 0;
}
} }
}
if (_grfconfig_newgame == NULL) { /* Check if item is valid */
_grfconfig_newgame = c; if (!FillGRFDetails(c, is_static)) {
} else { const char *msg;
GRFConfig *c2;
/* Attach the label to the end of the list */ if (HASBIT(c->flags, GCF_NOT_FOUND)) {
for (c2 = _grfconfig_newgame; c2->next != NULL; c2 = c2->next); msg = "not found";
c2->next = c; } 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) static void GRFSaveConfig(IniFile *ini, const char *grpname, const GRFConfig *list)
{ {
IniGroup *group = ini_getgroup(ini, grpname, -1); IniGroup *group = ini_getgroup(ini, grpname, -1);
@ -1575,7 +1596,8 @@ void LoadFromConfig(void)
{ {
IniFile *ini = ini_load(_config_file); IniFile *ini = ini_load(_config_file);
HandleSettingDescs(ini, ini_load_settings, ini_load_setting_list); 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); ini_free(ini);
} }
@ -1585,6 +1607,7 @@ void SaveToConfig(void)
IniFile *ini = ini_load(_config_file); IniFile *ini = ini_load(_config_file);
HandleSettingDescs(ini, ini_save_settings, ini_save_setting_list); HandleSettingDescs(ini, ini_save_settings, ini_save_setting_list);
GRFSaveConfig(ini, "newgrf", _grfconfig_newgame); GRFSaveConfig(ini, "newgrf", _grfconfig_newgame);
GRFSaveConfig(ini, "newgrf-static", _grfconfig_static);
ini_save(_config_file, ini); ini_save(_config_file, ini);
ini_free(ini); ini_free(ini);
} }

Loading…
Cancel
Save