VOGONS


PX Player: play MID and XMI files under DOS

Topic actions

Reply 100 of 105, by Ant1020

User metadata
Rank Newbie
Rank
Newbie

Thanks for what you're doing. Always wanted to rip the music from Blood Bowl (1995) but sadly your uxx tool doesn't support it.

Reply 101 of 105, by bristlehog

User metadata
Rank Oldbie
Rank
Oldbie
Ant1020 wrote on 2025-05-29, 11:49:

Thanks for what you're doing. Always wanted to rip the music from Blood Bowl (1995) but sadly your uxx tool doesn't support it.

Of course UXX doesn't support it, since Blood Bowl has its XMI files compressed with an old and obscure PKWARE DCL library. I've been able to extract and decompress them, using ChatGPT and Python. Took me some six or seven hours - mostly spent trying approaches that didn't work - QuickBMS, Dragon Unpacker etc.

Python code
import os, struct, pwexplode

# Get pwexplode.py here: https://github.com/Schallaven/pwexplode/blob/master/pwexplode.py

def extract_xmi_from_music_wad(path='music.wad'):
data = open(path, 'rb').read()
file_count = struct.unpack_from('<H', data, 0)[0]
header_base = 2
entry_size = 22

# parse directory
entries = []
for i in range(file_count):
base = header_base + i * entry_size
# first 14 bytes contain the file name
raw_name = data[base : base+14]
name = raw_name.split(b'\x00',1)[0].decode('ascii', errors='ignore')
# then four-byte file size
size = struct.unpack_from('<I', data, base+14)[0]
# then four-byte file offset in the WAD
offset = struct.unpack_from('<I', data, base+18)[0]
entries.append((name, offset, size))

# extract
out_dir = 'xmi'
os.makedirs(out_dir, exist_ok=True)

print()

for name, offset, size in entries:
if not name.lower().endswith('.xmi'):
continue
chunk = data[offset: offset+size]
# must skip first four bytes which are not a part of PKWARE DCL format and contain uncompressed file size
expected_file_size = struct.unpack_from('<I', chunk)[0]
output_data = pwexplode.explode(chunk[4:])
with open(os.path.join(out_dir, name), 'wb') as f:
f.write(output_data)
print(f'Extracted {name}: {len(output_data)} bytes (expected {expected_file_size} bytes)')

if __name__ == '__main__':
extract_xmi_from_music_wad()

Here you can get fantastic wallpapers created by a friend of mine: patreon.com/Unpocodrillo

Reply 102 of 105, by Ant1020

User metadata
Rank Newbie
Rank
Newbie

Thank you so much, bristlehog!

Reply 103 of 105, by Ant1020

User metadata
Rank Newbie
Rank
Newbie

Sorry for the double post, but any idea how to play the XMIs properly using MIDI Player on foobar2000 please? I selected libADLMIDI output plugin but unfortunately Blood Bowl isn't listed in adlmidi banks. Should it be AIL (I think so) but which one?

Reply 104 of 105, by bristlehog

User metadata
Rank Oldbie
Rank
Oldbie
Ant1020 wrote on 2025-05-31, 13:01:

Sorry for the double post, but any idea how to play the XMIs properly using MIDI Player on foobar2000 please? I selected libADLMIDI output plugin but unfortunately Blood Bowl isn't listed in adlmidi banks. Should it be AIL (I think so) but which one?

Apparently, Blood Bowl uses the default MIDPAK.AD timbre bank by The Fat Man (George Alistair Sanger). Select "OP3 (The Fat Man 2op set; Win9x)" ADLMIDI bank - it's seemingly the same bank, but with stereo capabilities powered by the OPL3 chip.

Disable "Enable soft panning" switch if you want to hear the authentic mono Adlib sound instead of stereo.

Here you can get fantastic wallpapers created by a friend of mine: patreon.com/Unpocodrillo

Reply 105 of 105, by GL1zdA

User metadata
Rank Oldbie
Rank
Oldbie
bristlehog wrote on 2025-05-28, 07:41:
I've tried it and there's definitely a problem with THM*.XMI, both GM and FM. Using PX in verbose mode, I see that no timbres a […]
Show full quote
GL1zdA wrote on 2024-10-18, 12:14:

I've tried PX player with the System Shock 1 XMI files and I don't get any sound. It works for the TEST.XMI music used in setup, but I hear nothing when I try to play any of the GENMIDI/THMx.XMI files. Any hints, what am I doing wrong?

I've tried it and there's definitely a problem with THM*.XMI, both GM and FM. Using PX in verbose mode, I see that no timbres are installed while trying to play THM*.XMI from FM folder, which means that there are no instruments to play the XMIDI sequence(s) with. In comparison, timbres are installed normally when playing, say, END.XMI.

I've tinkered a bit and found that the bug is caused by AIL 2.0 library itself. There's the function, AIL_timbre_request(), that scans the sequence for needed timbres, and it returns no required timbres for THMx.XMI sequences.

System Shock itself does not use AIL 2.0: the floppy version relies on AIL/32, while the CD version uses Miles Sound System. So apparently PX Player itself has nothing to do with this bug, which probably was fixed later in AIL/32 and MSS.

I've tried to play THM0.XMI with Miles Sound System's XMIPLAY tool v. 6.5, and Miles Sound Player for Windows, both from 2002 - neither can play it. Same with XP32 tool from AIL/32 v. 1.05.

So it becomes apparent that some of System Shock's XMI files are indeed cursed; not sure how Foobar2000's foo_midi addon authors managed to overcome this.

Thanks for investigating this. I was hoping the player will be able to generate te „environment” affected versions of the songs, but I guess recording it from the game is the only option.

getquake.gif | InfoWorld/PC Magazine Indices