diff --git a/lumps/dmxgus/gen-ultramid b/lumps/dmxgus/gen-ultramid index a8a37bfb..f029b16a 100755 --- a/lumps/dmxgus/gen-ultramid +++ b/lumps/dmxgus/gen-ultramid @@ -43,6 +43,14 @@ import sys import config import stats +HEADER_TEXT = """ +# Freedoom GUS config. +# Autogenerated by the gen-ultramid script. +# Please do not manually edit this file! +# The ordering of entries in this file is significant, to work around a +# bug in Doom's DMX sound library. +""" + def normalize_stats(stats): """Normalize the gathered instrument statistics. @@ -154,6 +162,39 @@ def mapping_for_size(size): return result +def instrument_patches(mappings): + """Returns list of MIDI instruments in an appropriate order for output. + + The ordering in the output file is important, because of a bug in the + DMX sound library; when patches are shared between instruments it is + only possible to refer to instruments listed earlier in the file. + + Args: + mappings: List of mappings from instrument ID to leader instrument. + Yields: + A tuple containing each MIDI instrument number and patch file name + to load. + """ + done_instr_ids = set() + # Make multiple passes until we've done all the instruments. + while len(done_instr_ids) < len(config.GUS_INSTR_PATCHES): + made_progress = False + for instr_id, name in sorted(config.GUS_INSTR_PATCHES.items()): + for mapping in mappings: + mapped_instr_id = mapping[instr_id] + if (instr_id != mapped_instr_id and + mapped_instr_id not in done_instr_ids): + break + else: + if instr_id not in done_instr_ids: + yield instr_id, name + done_instr_ids.add(instr_id) + made_progress = True + + assert made_progress, ( + "infinite loop while producing patches list") + + if len(sys.argv) != 2: print("Usage: %s " % sys.argv[0]) sys.exit(1) @@ -166,11 +207,9 @@ mappings = ( ) with open(sys.argv[1], "w") as output: - output.write("# Freedoom GUS config.\n" - "# Autogenerated by the gen-ultramid script.\n" - "# Please do not manually edit this file!\n") + output.write(HEADER_TEXT.lstrip()) - for instr_id, name in sorted(config.GUS_INSTR_PATCHES.items()): + for instr_id, name in instrument_patches(mappings): line = "%i, %i, %i, %i, %i, %s" % ( instr_id, mappings[0][instr_id],