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

This commit is contained in:
peter1138 2006-12-12 19:38:41 +00:00
parent 208b466181
commit be3e653db3
6 changed files with 134 additions and 60 deletions

View File

@ -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;

View File

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

View File

@ -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;
}

View File

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

View File

@ -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 {

View File

@ -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;
}
}
/* 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;
}
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;
}
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);
}