Skip to content

Instantly share code, notes, and snippets.

@w4kfu
Last active January 17, 2024 09:47
Show Gist options
  • Save w4kfu/17a29bfd31486c70bb5dba4aaa9ae782 to your computer and use it in GitHub Desktop.
Save w4kfu/17a29bfd31486c70bb5dba4aaa9ae782 to your computer and use it in GitHub Desktop.
Stupid Invaders ADP to WAV
import struct
import wave
import argparse
amplitude_lookuptable = [
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0010,
0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F, 0x0022,
0x0025, 0x0029, 0x002D, 0x0032, 0x0037, 0x003C, 0x0042, 0x0049,
0x0050, 0x0058, 0x0061, 0x006B, 0x0076, 0x0082, 0x008F, 0x009D,
0x00AD, 0x00BE, 0x00D1, 0x00E6, 0x00FD, 0x0117, 0x0133, 0x0151,
0x0173, 0x0198, 0x01C1, 0x01EE, 0x0220, 0x0256, 0x0292, 0x02D4,
0x031C, 0x036C, 0x03C3, 0x0424, 0x048E, 0x0502, 0x0583, 0x0610,
0x06AB, 0x0756, 0x0812, 0x08E0, 0x09C3, 0x0ABD, 0x0BD0, 0x0CFF,
0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE, 0x1706, 0x1954, 0x1BDC,
0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B, 0x3BB9,
0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF
]
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='adp file converter launch options')
parser.add_argument('adp_file', action='store', default='', help='adp file to convert')
parser.add_argument('-o', dest='output_file', help="Output wave file", required=True, metavar='output_file')
args = parser.parse_args()
fd = open(args.adp_file, "rb")
sig, nchannels, length = struct.unpack("<III", fd.read(0x0C))
if sig != 0x46524544:
raise ValueError("[-] Wrong magic")
if nchannels not in [1, 2]:
raise ValueError("[-] Wrong number of channels")
#print "[+] nchannels : %d" % nchannels
#print "[+] length : 0x%08X" % length
audio_data = fd.read(length)
wave_output = wave.open(args.output_file, "wb")
# BitsPerSample : 16
# SampleRate : 22050
wave_output.setparams((nchannels, 2, 22050, 0, 'NONE', 'not compressed'))
v_0 = 0x00
v_1 = 0x00
for i in xrange(0, len(audio_data), nchannels):
# convert sample
s1 = struct.unpack("<B", audio_data[i])[0]
if (s1 & 0x80) != 0x00:
v_0 = (v_0 - amplitude_lookuptable[s1 & 0x7F])
else:
v_0 = (v_0 + amplitude_lookuptable[s1])
wave_output.writeframes(struct.pack("<H", (v_0 & 0xFFFF)))
if nchannels == 0x02:
# convert sample
s2 = struct.unpack("<B", audio_data[i + 1])[0]
if (s2 & 0x80) != 0x00:
v_1 = (v_1 - amplitude_lookuptable[s2 & 0x7F])
else:
v_1 = (v_1 + amplitude_lookuptable[s2])
wave_output.writeframes(struct.pack("<H", (v_1 & 0xFFFF)))
wave_output.close()
@Kidpaddleetcie
Copy link

Alors là, je me dis une chose: WOAW, quelqu'un qui s'intéresse à Stupid Invaders :D

@jebez1
Copy link

jebez1 commented Jan 17, 2024

It doesn't work , replace :

xrange by range ( https://stackoverflow.com/questions/94935/what-is-the-difference-between-range-and-xrange-functions-in-python-2-x )

According to ChatGPT 3.5 :
s1 = struct.unpack("<B", audio_data[i])[0] by s1 = audio_data[i]
s2 = struct.unpack("<B", audio_data[i + 1])[0] by s2 = audio_data[i + 1] .

E.g. :
C:\Windows\System32>python D:\Games\adp_converter.py -o D:\games\credits.wav "C:\Program Files (x86)\Xilam\Stupid Invaders\Music\credits.adp"
works now .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment