Guest User

vgm_to_bytebeat

a guest
Nov 1st, 2020
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.79 KB | None | 0 0
  1. # vgm_to_bytebeat (see https://battleofthebits.org/arena/Entry/vgm+engine/39556/)
  2.  
  3. import sys
  4.  
  5. def rev_end(num, run=0, pos=0):
  6.     if not num:
  7.         return run
  8.     return rev_end(num[1:], run | (num[0] << (pos * 8)), pos + 1)
  9.  
  10. def convert(b):
  11.     d = b + 35
  12.     if d >= 92:
  13.         d += 1
  14.     return d
  15.  
  16. if len(sys.argv) < 3:
  17.     print('Usage: {} <infile> <outfile>'.format(sys.argv[0]))
  18.     sys.exit(1)
  19.  
  20. infile = open(sys.argv[1], 'rb')
  21. vgm_data = infile.read()
  22. infile.close()
  23.  
  24. if vgm_data[0x00:0x04] != b'Vgm ':
  25.     raise Exception('Not VGM file?')
  26.  
  27. vgm_eof = rev_end(vgm_data[0x04:0x08])
  28. vgm_ver = rev_end(vgm_data[0x08:0x0a])
  29. if vgm_ver >= 0x0150:
  30.     vgm_data_offset = rev_end(vgm_data[0x34:0x38]) + 0x34
  31. else:
  32.     vgm_data_offset = 0x40
  33.  
  34. outfile = open(sys.argv[2], 'wb')
  35.  
  36. tone = [0, 0, 0, 0]
  37. vol = [0xf, 0xf, 0xf, 0xf]
  38.  
  39. latch_ch = 0
  40. latch_vol = False
  41.  
  42. index = vgm_data_offset
  43. while index < vgm_eof:
  44.     inc = 1
  45.     cmd = vgm_data[index]
  46.  
  47.     if cmd == 0x00:
  48.         print('0x00 - nop?')
  49.     elif cmd == 0x50:
  50.         data = vgm_data[index+1]
  51.         print('0x50 - write 0x{:02x}'.format(data))
  52.  
  53.         if data & 0x80:
  54.             latch_ch = (data & 0x60) >> 5
  55.             latch_vol = bool(data & 0x10)
  56.             print('  latch ch{} {} = 0x{:02x}'.format(latch_ch, 'vol' if latch_vol else 'noise' if latch_ch == 3 else 'tone', data & 0x0f))
  57.  
  58.             if latch_vol:
  59.                 vol[latch_ch] = data & 0x0f
  60.             else:
  61.                 if latch_ch == 3:
  62.                     tone[latch_ch] = data & 0x07
  63.                 else:
  64.                     tone[latch_ch] = (tone[latch_ch] & 0xfff0) | (data & 0x000f)
  65.         else:
  66.             print('  data 0x{:02x}'.format(data & 0x3f))
  67.  
  68.             if latch_vol:
  69.                 vol[latch_ch] = data & 0x0f
  70.             else:
  71.                 if latch_ch == 3:
  72.                     tone[latch_ch] = data & 0x07
  73.                 else:
  74.                     tone[latch_ch] = (tone[latch_ch] & 0x000f) | ((data & 0x003f) << 4)
  75.  
  76.         inc = 2
  77.     elif 0x61 <= cmd <= 0x63:
  78.         print('0x{:02x} - wait frame'.format(cmd))
  79.         inc = 3 if cmd == 0x61 else 1
  80.         times = 1
  81.         if cmd == 0x61:
  82.             samps = rev_end(vgm_data[index+1:index+3])
  83.             frames = samps / 735
  84.             times = round(frames)
  85.             if frames != times:
  86.                 print('!! WARNING !! - non-NTSC frame wait ({} frames), timing will be off!'.format(frames))
  87.         elif cmd == 0x63:
  88.             print('!! WARNING !! - non-NTSC frame wait, timing will be off!')
  89.  
  90.         print('   ', tone, vol)
  91.  
  92.         tone_high = [(t & 0x3c0) >> 6 for t in tone[0:3]]
  93.         tone_low = [(t & 0x03f) for t in tone[0:3]]
  94.         tone_data = [x for y in zip(tone_high, tone_low) for x in y] + [tone[3]]
  95.         outdata = tone_data + vol
  96.  
  97.         print('    {}'.format(outdata))
  98.         outbytes = bytes(convert(b) for b in outdata)
  99.         for _ in range(times):
  100.             outfile.write(outbytes)
  101.         print('    {} (x{})'.format(str(outbytes, 'ascii'), times))
  102.     elif cmd == 0x66:
  103.         print('0x66 - end of sound data')
  104.         break
  105.     else:
  106.         print('!! WARNING !! - unknown command 0x{:02x} @ 0x{:08x}'.format(cmd, index))
  107.    
  108.     index += inc
  109.  
  110. outfile.close()
  111.  
Add Comment
Please, Sign In to add comment