Advertisement
Guest User

YUNO_Switch_sprite_assembler.py

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