initial commit: llamamod 0.2.0 – reverse-engineered level formats (wad, map, trak, text, stpc), python tools and notes, java mod manager (iso install, mod pipeline with exe patching, save editor, wine/windows launcher) with mods (test world, debug wireframe, mirror, randomizer, fog, cheats, intro skip, practice, free camera, boot to level, level projects) and the 3d level editor (geometry, objects, cross-world import, environment, textures, play-test, manual)
This commit is contained in:
commit
b36a366240
826 files changed
+105304
No files matched your search
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Dekodiert Argonaut-ASF-Musik (v2.1, 4-Bit-ADPCM) wie asfcodec.adl aus dem Spiel.
|
||||
|
||||
Nachgebaut aus der Disassembly von asfcodec.adl (Routinen 0x26e01969 / 0x26e01ca1):
|
||||
Filter 0: s = s1 + (n << shift)
|
||||
Filter 1: s = 2*s1 - s2 + (n << shift) (+ Übertrag aus 'adc', s. u.)
|
||||
- kein Clipping; Ausgabe wird als 16 Bit gespeichert (Überlauf = Wrap)
|
||||
- s1 läuft innerhalb eines Blocks ungekürzt im Register weiter,
|
||||
am Blockanfang wird es aus dem 16-Bit-Puffer gelesen
|
||||
- s2 wird immer aus dem 16-Bit-Puffer gelesen
|
||||
Aufruf: asf2wav.py eingabe.asf ausgabe.wav
|
||||
"""
|
||||
import array
|
||||
import struct
|
||||
import sys
|
||||
import wave
|
||||
|
||||
M32 = 0xFFFFFFFF
|
||||
|
||||
|
||||
def s32(x):
|
||||
x &= M32
|
||||
return x - (1 << 32) if x & 0x80000000 else x
|
||||
|
||||
|
||||
def wrap16(x):
|
||||
return ((x + 0x8000) & 0xFFFF) - 0x8000
|
||||
|
||||
|
||||
def decode(data):
|
||||
off = struct.unpack_from('<I', data, 12)[0]
|
||||
nblocks, _, _, rate, _, flags = struct.unpack_from('<IIIHHI', data, off)
|
||||
ch = 2 if flags & 2 else 1
|
||||
p = off + 20
|
||||
out = array.array('h', bytes(nblocks * 32 * ch * 2))
|
||||
mem = [[0, 0] for _ in range(ch)] # gespeicherte 16-Bit-Werte: [vorletztes, letztes]
|
||||
o = 0
|
||||
for _ in range(nblocks):
|
||||
for c in range(ch):
|
||||
ctl = data[p]
|
||||
blk = data[p + 1:p + 17]
|
||||
p += 17
|
||||
cl = (ctl >> 4) + 2
|
||||
prev2, prev1 = mem[c]
|
||||
eax = prev1 # Blockanfang: s1 aus dem Speicher
|
||||
k = o + c
|
||||
for byte in blk:
|
||||
for nib in (byte >> 4, byte & 15):
|
||||
n = nib - 16 if nib & 8 else nib
|
||||
edx = s32((n * 16) << cl)
|
||||
if ctl & 4:
|
||||
ebx = s32(eax << 7)
|
||||
a = s32(-prev2 << 6)
|
||||
carry = ((a & M32) + (edx & M32)) >> 32
|
||||
eax = s32(a + edx + ebx + carry) >> 6
|
||||
else:
|
||||
eax = s32((eax << 6) + edx) >> 6
|
||||
w = wrap16(eax)
|
||||
out[k] = w
|
||||
k += ch
|
||||
prev2, prev1 = prev1, w
|
||||
mem[c] = [prev2, prev1]
|
||||
o += 32 * ch
|
||||
return rate, ch, out
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
rate, ch, pcm = decode(open(sys.argv[1], 'rb').read())
|
||||
with wave.open(sys.argv[2], 'wb') as w:
|
||||
w.setnchannels(ch)
|
||||
w.setsampwidth(2)
|
||||
w.setframerate(rate)
|
||||
w.writeframes(pcm.tobytes())
|
||||
Reference in new issue
Block a user