ref: ba65f433fe79b9a09f726ee4b818fe292315c77a
parent: 243df30e086c28e5cbac69ecf717c9475e374219
author: Simon Howard <[email protected]>
date: Sat Oct 20 21:20:31 EDT 2018
music: Allow shortened hashes for subst configs. Just as with (eg.) Git it's nice to be able to refer to as hash by a prefix instead of having to type the whole thing, it's convenient to be able to give a hash prefix in a substitute music configuration. This change to the internals will also make it simpler to support a preconfigured table of filenames.
--- a/src/i_sdlmusic.c
+++ b/src/i_sdlmusic.c
@@ -78,8 +78,8 @@
typedef struct
{
- sha1_digest_t hash;
- char *filename;
+ const char *hash_prefix;
+ const char *filename;
} subst_music_t;
// Structure containing parsed metadata read from a digital music track:
@@ -371,7 +371,7 @@
}
}
-static void ReadLoopPoints(char *filename, file_metadata_t *metadata)
+static void ReadLoopPoints(const char *filename, file_metadata_t *metadata)
{
FILE *fs;
char header[4];
@@ -422,11 +422,12 @@
// Given a MUS lump, look up a substitute MUS file to play instead
// (or NULL to just use normal MIDI playback).
-static char *GetSubstituteMusicFile(void *data, size_t data_len)
+static const char *GetSubstituteMusicFile(void *data, size_t data_len)
{
sha1_context_t context;
sha1_digest_t hash;
- char *filename;
+ const char *filename;
+ char hash_str[sizeof(sha1_digest_t) * 2 + 1];
unsigned int i;
// Don't bother doing a hash if we're never going to find anything.
@@ -439,6 +440,13 @@
SHA1_Update(&context, data, data_len);
SHA1_Final(hash, &context);
+ // Build a string representation of the hash.
+ for (i = 0; i < sizeof(sha1_digest_t); ++i)
+ {
+ M_snprintf(hash_str + i * 2, sizeof(hash_str) - i * 2,
+ "%02x", hash[i]);
+ }
+
// Look for a hash that matches.
// The substitute mapping list can (intentionally) contain multiple
// filename mappings for the same hash. This allows us to try
@@ -448,7 +456,7 @@
for (i = 0; i < subst_music_len; ++i)
{
- if (memcmp(hash, subst_music[i].hash, sizeof(hash)) == 0)
+ if (M_StringStartsWith(hash_str, subst_music[i].hash_prefix))
{
filename = subst_music[i].filename;
@@ -476,24 +484,6 @@
memcpy(&subst_music[subst_music_len - 1], subst, sizeof(subst_music_t));
}
-static int ParseHexDigit(char c)
-{
- c = tolower(c);
-
- if (c >= '0' && c <= '9')
- {
- return c - '0';
- }
- else if (c >= 'a' && c <= 'f')
- {
- return 10 + (c - 'a');
- }
- else
- {
- return -1;
- }
-}
-
static char *GetFullPath(char *base_filename, char *path)
{
char *basedir, *result;
@@ -528,6 +518,41 @@
return result;
}
+static const char *ReadHashPrefix(char *line)
+{
+ char *result;
+ char *p;
+ int i, len;
+
+ for (p = line; *p != '\0' && !isspace(*p) && *p != '='; ++p)
+ {
+ if (!isxdigit(*p))
+ {
+ return NULL;
+ }
+ }
+
+ len = p - line;
+ if (len == 0 || len > sizeof(sha1_digest_t) * 2)
+ {
+ return NULL;
+ }
+
+ result = malloc(len + 1);
+ if (result == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0; i < len; ++i)
+ {
+ result[i] = tolower(line[i]);
+ }
+ result[len] = '\0';
+
+ return result;
+}
+
// Parse a line from substitute music configuration file; returns error
// message or NULL for no error.
@@ -535,7 +560,6 @@
{
subst_music_t subst;
char *p;
- int hash_index;
// Strip out comments if present.
p = strchr(line, '#');
@@ -558,34 +582,13 @@
return NULL;
}
- // Read hash.
- hash_index = 0;
- while (*p != '\0' && *p != '=' && !isspace(*p))
+ subst.hash_prefix = ReadHashPrefix(p);
+ if (subst.hash_prefix == NULL)
{
- int d1, d2;
-
- d1 = ParseHexDigit(p[0]);
- d2 = ParseHexDigit(p[1]);
-
- if (d1 < 0 || d2 < 0)
- {
- return "Invalid hex digit in SHA1 hash";
- }
- else if (hash_index >= sizeof(sha1_digest_t))
- {
- return "SHA1 hash too long";
- }
-
- subst.hash[hash_index] = (d1 << 4) | d2;
- ++hash_index;
-
- p += 2;
+ return "Invalid hash prefix";
}
- if (hash_index != sizeof(sha1_digest_t))
- {
- return "SHA1 hash too short";
- }
+ p += strlen(subst.hash_prefix);
// Skip spaces.
for (; *p != '\0' && isspace(*p); ++p);
@@ -1139,7 +1142,7 @@
return len > 4 && !memcmp(mem, "MThd", 4);
}
-static boolean ConvertMus(byte *musdata, int len, char *filename)
+static boolean ConvertMus(byte *musdata, int len, const char *filename)
{
MEMFILE *instream;
MEMFILE *outstream;
@@ -1167,7 +1170,8 @@
static void *I_SDL_RegisterSong(void *data, int len)
{
- char *filename;
+ const char *filename;
+ char *tmp_filename;
Mix_Music *music;
if (!music_initialized)
@@ -1204,17 +1208,17 @@
// MUS files begin with "MUS"
// Reject anything which doesnt have this signature
- filename = M_TempFile("doom.mid");
+ tmp_filename = M_TempFile("doom.mid");
if (IsMid(data, len) && len < MAXMIDLENGTH)
{
- M_WriteFile(filename, data, len);
+ M_WriteFile(tmp_filename, data, len);
}
else
{
// Assume a MUS file and try to convert
- ConvertMus(data, len, filename);
+ ConvertMus(data, len, tmp_filename);
}
// Load the MIDI. In an ideal world we'd be using Mix_LoadMUS_RW()
@@ -1227,7 +1231,7 @@
if (midi_server_initialized)
{
music = NULL;
- if (!I_MidiPipe_RegisterSong(filename))
+ if (!I_MidiPipe_RegisterSong(tmp_filename))
{
fprintf(stderr, "Error loading midi: %s\n",
"Could not communicate with midiproc.");
@@ -1236,7 +1240,7 @@
else
#endif
{
- music = Mix_LoadMUS(filename);
+ music = Mix_LoadMUS(tmp_filename);
if (music == NULL)
{
// Failed to load
@@ -1250,11 +1254,11 @@
if (strlen(snd_musiccmd) == 0)
{
- remove(filename);
+ remove(tmp_filename);
}
}
- free(filename);
+ free(tmp_filename);
return music;
}