Advertisement
Guest User

YUNO_Switch_sprite_assembler.py

a guest
May 22nd, 2019
258
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.07 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. # With much code copying from Nimms <nimms@ya.ru> and anon
  4.  
  5. import sys
  6. import glob
  7. import os
  8. import struct
  9. import codecs
  10. from PIL import Image
  11. from itertools import product
  12.  
  13. # endianness, depends on target platform (> = big, < = little)
  14. BYTE_ORDER = '<'
  15. BLOCK_SIZE = 32
  16.  
  17. if len(sys.argv) == 1:
  18.     print("No files given.", file=sys.stderr)
  19.     exit(1)
  20.  
  21. args = sys.argv[1:]
  22. if len(sys.argv) == 0:
  23.     args = glob.glob('*.mvl')
  24. else:
  25.     for i, arg in enumerate(args):
  26.         if '*' in arg:
  27.             args = args[:i] + glob.glob(arg) + args[i+1:]
  28.  
  29. for arg in args:
  30.     arg = os.path.abspath(os.path.splitext(arg)[0])
  31.     if arg[-1] == '_':
  32.         arg = arg[:-1]
  33.  
  34.     arg_basename = os.path.basename(arg)
  35.     if not os.path.exists(arg_basename):
  36.         os.mkdir(arg_basename)
  37.     os.chdir(arg_basename)
  38.  
  39.     print(arg_basename)
  40.    
  41.     records_count = 0
  42.     map_count = 0
  43.     states = []
  44.     records = []
  45.     map = []
  46.     map_start = None
  47.    
  48.     with open(arg + '_.mvl', 'rb') as f:
  49.         # 4 chars: MVL1
  50.         f.read(4)
  51.         # uint32: count of states
  52.         states_count = struct.unpack(BYTE_ORDER + 'I', f.read(4))[0]
  53.         #print(states_count)
  54.         # uint32: input width
  55.         INPUT_WIDTH = struct.unpack(BYTE_ORDER + 'I', f.read(4))[0]
  56.         #print(INPUT_WIDTH)
  57.         # 20 zeros
  58.         f.read(20)
  59.         # 64 characters
  60.         shit = str(f.read(64), encoding='ascii').strip('\0')
  61.         #print(shit)
  62.        
  63.        
  64.         for i in range(states_count):
  65.             # uint32: output width
  66.             SCREEN_WIDTH = struct.unpack(BYTE_ORDER + 'I', f.read(4))[0]
  67.             # uint32: output height
  68.             SCREEN_HEIGHT = struct.unpack(BYTE_ORDER + 'I', f.read(4))[0]
  69.             # uint32: idk
  70.             idk = struct.unpack(BYTE_ORDER + 'I', f.read(4))[0]
  71.             # 4 zeros
  72.             f.read(4)
  73.             # uint32: count of coordinates records
  74.             records_count = struct.unpack(BYTE_ORDER + 'I', f.read(4))[0]
  75.             # uint32: beginning of coordinates records
  76.             records_start = struct.unpack(BYTE_ORDER + 'I', f.read(4))[0]
  77.             # uint32: count of records to read
  78.             count = struct.unpack(BYTE_ORDER + 'I', f.read(4))[0]
  79.             # uint32: beginning of records to read
  80.             start = struct.unpack(BYTE_ORDER + 'I', f.read(4))[0]
  81.             # 32 chars: state name
  82.             id = str(f.read(32), encoding='ascii').strip('\0')
  83.            
  84.             if map_start == None:
  85.                 map_start = start
  86.            
  87.             start = (start - map_start) // 2
  88.             count
  89.            
  90.             map_count += count
  91.            
  92.             if len(id) == 9:
  93.                 states.append({'id': id, 'count': count, 'start': start})
  94.             else:
  95.                 states[-1].setdefault('overlays', {}).setdefault(id[-2], []).append({'count': count, 'start': start})
  96.            
  97.             #print(id, count, start, sep='\t')
  98.         #print()
  99.         #print(output_width, output_height)
  100.         #print()
  101.        
  102.         #print(records_count)
  103.         for i in range(records_count):
  104.             # float32: block position on the screen, X
  105.             x1 = int(struct.unpack(BYTE_ORDER + 'f', f.read(4))[0])# + 1
  106.             # float32: block position on the screen, Y
  107.             y1 = int(struct.unpack(BYTE_ORDER + 'f', f.read(4))[0])# + 1
  108.             # 4 zeros
  109.             f.read(4)
  110.             # float32: block position in the image, X
  111.             x2 = struct.unpack(BYTE_ORDER + 'f', f.read(4))[0]# - 1
  112.             # float32: block position in the image, Y
  113.             y2 = struct.unpack(BYTE_ORDER + 'f', f.read(4))[0]# - 1
  114.             #print(x1, y1, x2, y2)
  115.             records.append((x1, y1, x2, y2))
  116.         #print()
  117.        
  118.         #print(map_count)
  119.         for i in range(map_count):
  120.             (idx,) = struct.unpack(BYTE_ORDER + 'H', f.read(2))
  121.             map.append(idx)
  122.    
  123.     with Image.open(arg + '.png') as image:
  124.  
  125.         # empty image
  126.         empty_im = Image.new('RGBA', (SCREEN_WIDTH, SCREEN_HEIGHT), (0, 0, 0, 0))
  127.        
  128.         for s in states:
  129.             basestate_fname = '{}_{}'.format(arg_basename, s['id'])
  130.             print(s['id'])
  131.            
  132.             s_im = basestate_im = empty_im.copy()
  133.            
  134.             for i in range(s['start'], s['start'] + s['count'], 6):
  135.                 c = records[map[i]]
  136.                 in_box = (int(c[2] * image.size[0]) + 1, int(c[3] * image.size[1]) + 1, int(c[2] * image.size[0]) + BLOCK_SIZE - 1, int(c[3] * image.size[1]) + BLOCK_SIZE - 1)
  137.                 out_box = (SCREEN_WIDTH//2 + c[0], SCREEN_HEIGHT//2 + c[1])
  138.                 region = image.crop(in_box)
  139.                 s_im.paste(region, out_box, region)
  140.            
  141.             overlay_images = {}
  142.            
  143.             for (overlay, l) in s['overlays'].items():
  144.                 overlay_images[overlay] = []
  145.                 for (i, x) in enumerate(l):
  146.                     overlay_images[overlay].append((i, empty_im.copy()))
  147.                     s_im = overlay_images[overlay][-1][1]
  148.                    
  149.                     for j in range(x['start'], x['start'] + x['count'], 6):
  150.                         c = records[map[j]]
  151.                         in_box = (int(c[2] * image.size[0]) + 1, int(c[3] * image.size[1]) + 1, int(c[2] * image.size[0]) + BLOCK_SIZE - 1, int(c[3] * image.size[1]) + BLOCK_SIZE - 1)
  152.                         out_box = (SCREEN_WIDTH//2 + c[0], SCREEN_HEIGHT//2 + c[1])
  153.                         region = image.crop(in_box)
  154.                         s_im.paste(region, out_box, region)
  155.            
  156.             for overlays in product(*overlay_images.values()):
  157.                 s_im = basestate_im.copy()
  158.                 s_fname = basestate_fname
  159.                
  160.                 for (overlay, (num, overlay_im)) in zip(s['overlays'].keys(), overlays):
  161.                     s_fname += overlay + str(num)
  162.                     s_im.paste(overlay_im, mask=overlay_im)
  163.                
  164.                 s_im.save(s_fname + '.png')
  165.                 s_im.close()
  166.             basestate_im.close()
  167.             for l in overlay_images.values():
  168.                 for (num, im) in l:
  169.                     im.close()
  170.     print()
  171. os.chdir('..')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement