[xmp] Parse module-specific configuration file

Certain modules need specific adjustments to play correctly. It's not
possible to automatically detect these modules, so a module-specific
configuration file was added. Adjustments include: workaround for
module conversion errors, differences between protracker versions,
and custom replay parameters for specific modules.

Signed-off-by: Claudio Matsuoka <cmatsuoka@gmail.com>
master
Claudio Matsuoka 13 years ago
parent cf788f338f
commit 30f68b150f
  1. 4
      src/Makefile
  2. 3
      src/common.h
  3. 19
      src/main.c
  4. 33
      src/modules.conf
  5. 2
      src/options.c
  6. 127
      src/read_config.c

@ -38,8 +38,8 @@ install-docs: $(SRC_PATH)/xmp.1
@[ -d $(DESTDIR)$(MANDIR) ] || mkdir -p $(DESTDIR)$(MANDIR)
@$(INSTALL) -m644 $+ $(DESTDIR)$(MANDIR)
install-conf: $(SRC_PATH)/xmp.conf
@echo Installing configuration file in $(DESTDIR)$(SYSCONFDIR)
install-conf: $(SRC_PATH)/xmp.conf $(SRC_PATH)/modules.conf
@echo Installing configuration files in $(DESTDIR)$(SYSCONFDIR)
@[ -d $(DESTDIR)$(SYSCONFDIR) ] || mkdir -p $(DESTDIR)$(SYSCONFDIR)
@$(INSTALL) -m644 $+ $(DESTDIR)$(SYSCONFDIR)

@ -15,7 +15,7 @@ struct options {
int loop; /* loop module */
int random; /* play in random order */
int reverse; /* reverse stereo channels */
int vblank; /* use vblank timing */
int flags; /* player flags */
int verbose; /* verbosity level */
int silent; /* silent output */
int info; /* display information and exit */
@ -43,6 +43,7 @@ int report(char *, ...);
/* option */
void get_options(int, char **, struct options *);
int read_config(struct options *);
void read_modconf(struct options *, unsigned char *);
/* terminal */
int set_tty(void);

@ -147,7 +147,7 @@ int main(int argc, char **argv)
xmp_context handle;
struct xmp_module_info mi;
struct xmp_frame_info fi;
struct options opt;
struct options opt, save_opt;
struct control control;
int i;
int first;
@ -268,7 +268,11 @@ int main(int argc, char **argv)
}
lf_flag = 0;
memcpy(&save_opt, &opt, sizeof (struct options));
for (first = optind; optind < argc; optind++) {
memcpy(&opt, &save_opt, sizeof (struct options));
if (opt.verbose > 0) {
if (lf_flag)
report("\n");
@ -310,6 +314,10 @@ int main(int argc, char **argv)
}
continue;
}
xmp_get_module_info(handle, &mi);
read_modconf(&opt, mi.md5);
skipprev = 0;
control.time = 0.0;
control.loop = opt.loop;
@ -336,18 +344,15 @@ int main(int argc, char **argv)
xmp_channel_mute(handle, i, opt.mute[i]);
}
/* Change timing if vblank specified */
/* Set player flags */
if (opt.vblank) {
xmp_set_player(handle, XMP_PLAYER_TIMING,
XMP_TIMING_VBLANK);
xmp_set_player(handle, XMP_PLAYER_FLAGS, opt.flags);
if (opt.flags & XMP_FLAGS_VBLANK) {
xmp_scan_module(handle);
}
/* Show module data */
xmp_get_module_info(handle, &mi);
if (opt.verbose > 0) {
info_mod(&mi);
}

@ -0,0 +1,33 @@
# Configuration for specific modules
# xmp will look for this file in /etc/xmp/modules.conf and
# $HOME/.xmp/modules.conf (both files will be read).
#
# Format is:
#
# [MD5sum]
# 8bit = yes/no Convert 16 bit samples to 8 bit
# amplify = <0|1|2|3> Amplification factor (default is 1)
# filter = yes/no Enable filters (affects IT only)
# fixloop = yes/no Use sample loop start value / 2
# fx9bug = yes/no Protracker 2.x effect 9 bug emulation
# interpolation = <method> Software mixer interpolation
# mono = yes/no Mono output
# mix = value Stereo channel separation (0 - 100)
# reverse = yes/no Reverse L/R stereo channels
# vblank = yes/no Force vblank timing instead of CIA
# "No Mercy" by Alf/VTL (added by Martin Willers)
[366ec0fa962aebee034aa2dbaa49aaea]
fx9bug = yes
# mod.souvenir of china
[93f146aeb758c39d8b5fbc98bf237a43]
fixloop = yes
# "siedler ii" (added by Daniel Åkerud)
[70aa034dfb2f1f73d9fdbafe131bb701]
vblank = yes
# Klisje paa klisje (added by Kjetil Torgrim Homme)
[e998012c700eb43af0321711305829b2]
vblank = yes

@ -266,7 +266,7 @@ void get_options(int argc, char **argv, struct options *options)
options->format |= XMP_FORMAT_UNSIGNED;
break;
case OPT_VBLANK:
options->vblank = 1;
options->flags |= XMP_FLAGS_VBLANK;
break;
case 'V':
puts("Extended Module Player " VERSION);

@ -94,16 +94,18 @@ int read_config(struct options *o)
val = strtok(NULL, " \t\n");
#define getval_yn(w,x,y) { \
#define getval_yn(x,w,y) { \
if (!strcmp(var,x)) { if (get_yesno (val)) w |= (y); \
else w &= ~(y); continue; } }
#define getval_no(x,y) { \
if (!strcmp(var,x)) { y = atoi (val); continue; } }
getval_yn(o->format, "8bit", XMP_FORMAT_8BIT);
getval_yn(o->format, "mono", XMP_FORMAT_MONO);
getval_yn(o->dsp, "filter", XMP_DSP_LOWPASS);
getval_yn("8bit", o->format, XMP_FORMAT_8BIT);
getval_yn("mono", o->format, XMP_FORMAT_MONO);
getval_yn("filter", o->dsp, XMP_DSP_LOWPASS);
getval_yn("loop", o->loop, 1);
getval_yn("reverse", o->reverse, 1);
getval_no("amplify", o->amplify);
getval_no("mix", o->mix);
/*getval_no("chorus", o->chorus);
@ -131,11 +133,6 @@ int read_config(struct options *o)
}
}
if (!strcmp(var, "loop")) {
o->loop = get_yesno(val);
continue;
}
if (!strcmp(var, "bits")) {
if (atoi(val) == 8)
o->format = XMP_FORMAT_8BIT;;
@ -147,7 +144,8 @@ int read_config(struct options *o)
o->ins_path = instrument_path;
continue;
}
/* If the line does not match any of the previous parameter,
/* If the line doesn't match any of the previous parameters,
* send it to the device driver
*/
if (o->dparm < MAX_DRV_PARM) {
@ -160,3 +158,112 @@ int read_config(struct options *o)
return 0;
}
static int compare_md5(unsigned char *d, char *digest)
{
int i;
for (i = 0; i < 16 && *digest; i++, digest += 2) {
char hex[3];
hex[0] = digest[0];
hex[1] = digest[1];
hex[2] = 0;
if (d[i] != strtoul(hex, NULL, 16))
return -1;
}
return 0;
}
static void parse_modconf(struct options *o, char *confname, unsigned char *md5)
{
FILE *rc;
char *hash, *var, *val, line[256];
int active = 0;
if ((rc = fopen(confname, "r")) == NULL)
return;
while (!feof(rc)) {
memset(line, 0, 256);
fscanf(rc, "%255[^\n]", line);
fgetc(rc);
/* Delete comments */
if ((hash = strchr(line, '#')))
*hash = 0;
if (line[0] == '[') {
if (compare_md5(md5, line + 1) == 0) {
active = 1;
}
continue;
}
if (!active)
continue;
delete_spaces(line);
if (!(var = strtok(line, "=\n")))
continue;
val = strtok(NULL, " \t\n");
getval_yn("8bit", o->format, XMP_FORMAT_8BIT);
getval_yn("mono", o->format, XMP_FORMAT_MONO);
getval_yn("filter", o->dsp, XMP_DSP_LOWPASS);
getval_yn("loop", o->loop, XMP_DSP_LOWPASS);
getval_yn("reverse", o->reverse, 1);
getval_no("amplify", o->amplify);
getval_no("mix", o->mix);
getval_yn("fixloop", o->flags, XMP_FLAGS_FIXLOOP);
getval_yn("fx9bug", o->flags, XMP_FLAGS_FX9BUG);
getval_yn("vblank", o->flags, XMP_FLAGS_VBLANK);
if (!strcmp(var, "interpolation")) {
if (!strcmp(val, "nearest")) {
o->interp = XMP_INTERP_NEAREST;
} else if (!strcmp(val, "linear")) {
o->interp = XMP_INTERP_LINEAR;
} else if (!strcmp(val, "spline")) {
o->interp = XMP_INTERP_SPLINE;
} else {
fprintf(stderr, "%s: unknown interpolation "
"type \"%s\"\n", confname, val);
}
}
}
fclose(rc);
}
void read_modconf(struct options *o, unsigned char *md5)
{
#if defined __EMX__
char myrc[PATH_MAX];
char *home = getenv("HOME");
snprintf(myrc, PATH_MAX, "%s\\.xmp\\modules.conf", home);
parse_modconf(o, "xmp-modules.conf", md5);
parse_modconf(o, myrc, md5);
#elif defined __AMIGA__
parse_modconf(o, "PROGDIR:modules.conf", md5);
#elif defined WIN32
char myrc[PATH_MAX];
char *home = getenv("SystemRoot");
snprintf(myrc, PATH_MAX, "%s/modules.conf", home);
parse_modconf(o, myrc, md5);
#else
char myrc[PATH_MAX];
char *home = getenv("HOME");
snprintf(myrc, PATH_MAX, "%s/.xmp/modules.conf", home);
parse_modconf(o, SYSCONFDIR "/modules.conf", md5);
parse_modconf(o, myrc, md5);
#endif
}

Loading…
Cancel
Save