summaryrefslogtreecommitdiff
path: root/src/settings.cpp
diff options
context:
space:
mode:
authoralberth <alberth@openttd.org>2014-05-24 19:12:48 +0000
committeralberth <alberth@openttd.org>2014-05-24 19:12:48 +0000
commitc1e7c32f070ff8f3aadb2373f543f58333740e70 (patch)
treeb369679726f1471ed9c1626977a0c758f7f8a9c8 /src/settings.cpp
parent8755c26793e9ba8f49cef7303e7b7517c69231e9 (diff)
downloadopenttd-c1e7c32f070ff8f3aadb2373f543f58333740e70.tar.xz
(svn r26611) -Feature: Save and load grfid and md5sum of newgrfs in config file (frosch)
Diffstat (limited to 'src/settings.cpp')
-rw-r--r--src/settings.cpp80
1 files changed, 72 insertions, 8 deletions
diff --git a/src/settings.cpp b/src/settings.cpp
index 11f30c150..5cbdce9d9 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -1408,6 +1408,40 @@ static void GameLoadConfig(IniFile *ini, const char *grpname)
}
/**
+ * Convert a character to a hex nibble value, or \c -1 otherwise.
+ * @param c Character to convert.
+ * @return Hex value of the character, or \c -1 if not a hex digit.
+ */
+static int DecodeHexNibble(char c)
+{
+ if (c >= '0' && c <= '9') return c - '0';
+ if (c >= 'A' && c <= 'F') return c + 10 - 'A';
+ if (c >= 'a' && c <= 'f') return c + 10 - 'a';
+ return -1;
+}
+
+/**
+ * Parse a sequence of characters (supposedly hex digits) into a sequence of bytes.
+ * After the hex number should be a \c '|' character.
+ * @param pos First character to convert.
+ * @param dest [out] Output byte array to write the bytes.
+ * @param dest_size Number of bytes in \a dest.
+ * @return Whether reading was successful.
+ */
+static bool DecodeHexText(char *pos, uint8 *dest, size_t dest_size)
+{
+ while (dest_size > 0) {
+ int hi = DecodeHexNibble(pos[0]);
+ int lo = (hi >= 0) ? DecodeHexNibble(pos[1]) : -1;
+ if (lo < 0) return false;
+ *dest++ = (hi << 4) | lo;
+ pos += 2;
+ dest_size--;
+ }
+ return *pos == '|';
+}
+
+/**
* Load a GRF configuration
* @param ini The configuration to read from.
* @param grpname Group name containing the configuration of the GRF.
@@ -1423,16 +1457,41 @@ static GRFConfig *GRFLoadConfig(IniFile *ini, const char *grpname, bool is_stati
if (group == NULL) return NULL;
for (item = group->item; item != NULL; item = item->next) {
- GRFConfig *c = new GRFConfig(item->name);
+ GRFConfig *c = NULL;
+
+ uint8 grfid_buf[4], md5sum[16];
+ char *filename = item->name;
+ bool has_grfid = false;
+ bool has_md5sum = false;
+
+ /* Try reading "<grfid>|" and on success, "<md5sum>|". */
+ has_grfid = DecodeHexText(filename, grfid_buf, lengthof(grfid_buf));
+ if (has_grfid) {
+ filename += 1 + 2 * lengthof(grfid_buf);
+ has_md5sum = DecodeHexText(filename, md5sum, lengthof(md5sum));
+ if (has_md5sum) filename += 1 + 2 * lengthof(md5sum);
+
+ uint32 grfid = grfid_buf[0] | (grfid_buf[1] << 8) | (grfid_buf[2] << 16) | (grfid_buf[3] << 24);
+ if (has_md5sum) {
+ const GRFConfig *s = FindGRFConfig(grfid, FGCM_EXACT, md5sum);
+ if (s != NULL) c = new GRFConfig(*s);
+ }
+ if (c == NULL && !FioCheckFileExists(filename, NEWGRF_DIR)) {
+ const GRFConfig *s = FindGRFConfig(grfid, FGCM_NEWEST_VALID);
+ if (s != NULL) c = new GRFConfig(*s);
+ }
+ }
+ if (c == NULL) c = new GRFConfig(filename);
/* Parse parameters */
if (!StrEmpty(item->value)) {
- c->num_params = ParseIntList(item->value, (int*)c->param, lengthof(c->param));
- if (c->num_params == (byte)-1) {
- SetDParamStr(0, item->name);
+ int count = ParseIntList(item->value, (int*)c->param, lengthof(c->param));
+ if (count < 0) {
+ SetDParamStr(0, filename);
ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY, WL_CRITICAL);
- c->num_params = 0;
+ count = 0;
}
+ c->num_params = count;
}
/* Check if item is valid */
@@ -1449,7 +1508,7 @@ static GRFConfig *GRFLoadConfig(IniFile *ini, const char *grpname, bool is_stati
SetDParam(1, STR_CONFIG_ERROR_INVALID_GRF_UNKNOWN);
}
- SetDParamStr(0, item->name);
+ SetDParamStr(0, StrEmpty(filename) ? item->name : filename);
ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_GRF, WL_CRITICAL);
delete c;
continue;
@@ -1459,7 +1518,7 @@ static GRFConfig *GRFLoadConfig(IniFile *ini, const char *grpname, bool is_stati
bool duplicate = false;
for (const GRFConfig *gc = first; gc != NULL; gc = gc->next) {
if (gc->ident.grfid == c->ident.grfid) {
- SetDParamStr(0, item->name);
+ SetDParamStr(0, c->filename);
SetDParamStr(1, gc->filename);
ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_DUPLICATE_GRFID, WL_CRITICAL);
duplicate = true;
@@ -1557,10 +1616,15 @@ static void GRFSaveConfig(IniFile *ini, const char *grpname, const GRFConfig *li
const GRFConfig *c;
for (c = list; c != NULL; c = c->next) {
+ /* Hex grfid (4 bytes in nibbles), "|", hex md5sum (16 bytes in nibbles), "|", file system path. */
+ char key[4 * 2 + 1 + 16 * 2 + 1 + MAX_PATH];
char params[512];
GRFBuildParamList(params, c, lastof(params));
- group->GetItem(c->filename, true)->SetValue(params);
+ char *pos = key + seprintf(key, lastof(key), "%08X|", BSWAP32(c->ident.grfid));
+ pos = md5sumToString(pos, lastof(key), c->ident.md5sum);
+ seprintf(pos, lastof(key), "|%s", c->filename);
+ group->GetItem(key, true)->SetValue(params);
}
}