Vearie

bz2stb.py - BZ2 Sprite Parser

Feb 6th, 2022 (edited)
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.16 KB | None | 0 0
  1. """This module provides a parser and writer for BZ2 .stb files and their plain text representations."""
  2. VERSION = 1.0
  3.  
  4. import re
  5. from ctypes import Structure, c_char, c_uint32, c_uint16
  6.  
  7. RE_TEXT_SPRITE = re.compile(r"^\s*\"(.*)\"\s+(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+0x(\w+)")
  8. RE_TEXT_FILE = re.compile(r"^\s*\@include \"(.+)\"")
  9.  
  10. ENCODING = "ascii"
  11.  
  12. class Sprite(Structure):
  13.     _fields_ = [
  14.         ("name", c_char*32), # Name used in ODF to refer to sprite
  15.         ("file", c_char*8), # Texture image game slices the sprite from
  16.         ("u", c_uint16), # x offset of sprite slice
  17.         ("v", c_uint16), # y offset of sprite slice
  18.         ("w", c_uint16), # Width of sprite slice
  19.         ("h", c_uint16), # Height of sprite slice
  20.         ("tw", c_uint16), # Texture width
  21.         ("th", c_uint16), # Texture height
  22.         ("flags", c_uint32)
  23.     ]
  24.    
  25.     def decoded(self):
  26.         return "\"%s\"\t\"%s\"\t%d\t%d\t%d\t%d\t%d\t%d\t0x%x" % (
  27.                 self.name.decode(encoding=ENCODING),
  28.                 self.file.decode(encoding=ENCODING),
  29.                 self.u, self.v,
  30.                 self.w, self.h,
  31.                 self.tw, self.th,
  32.                 self.flags
  33.             )
  34.  
  35. class STB:
  36.     def __init__(self, from_path=None):
  37.         self.sprites = []
  38.        
  39.         if from_path:
  40.             if from_path[-4::].casefold() == ".stb":
  41.                 self.read(from_path)
  42.             else:
  43.                 self.read_text(from_path)
  44.    
  45.     def __bytes__(self):
  46.         return b"".join(self.sprites)
  47.    
  48.     def read_text(self, path):
  49.         with open(path, "r") as f:
  50.             for line in f:
  51.                 match = RE_TEXT_FILE.match(line)
  52.                 if match:
  53.                     # TODO: Check name against bz2-esque context of file locality? (files discoverable in a bzone.cfg context)
  54.                     self.read_text(match.group(1)) # Will raise FileNotFoundError if not found.
  55.                     continue
  56.                
  57.                 match = RE_TEXT_SPRITE.match(line)
  58.                 if match:
  59.                     sprite = Sprite()
  60.                     sprite.name = match.group(1).encode(encoding=ENCODING)
  61.                     sprite.file = match.group(2).encode(encoding=ENCODING)
  62.                     sprite.u = int(match.group(3))
  63.                     sprite.v = int(match.group(4))
  64.                     sprite.w = int(match.group(5))
  65.                     sprite.h = int(match.group(6))
  66.                     sprite.tw = int(match.group(7))
  67.                     sprite.th = int(match.group(8))
  68.                     sprite.flags = int(match.group(9), 16)
  69.                     self.sprites += [sprite]
  70.                     continue
  71.    
  72.     def write_text(self, path):
  73.         with open(path, "w") as f:
  74.             f.write("sprite_tabel\n\n")
  75.             for sprite in self.sprites:
  76.                 f.write(sprite.decoded() + "\n")
  77.    
  78.     def read(self, path):
  79.         with open(path, "rb") as f:
  80.             while True:
  81.                 sprite = Sprite()
  82.                 if not f.readinto(sprite):
  83.                     break
  84.                 self.sprites += [sprite]
  85.    
  86.     def write(self, path):
  87.         with open(path, "wb") as f:
  88.             f.write(bytes(self))
  89.    
  90.     def show(self):
  91.         print("sprite_tabel\n")
  92.         for sprite in self.sprites:
  93.             print(sprite.decoded())
  94.  
  95. if __name__ == "__main__":
  96.     import sys, os
  97.     for sprite_file in sys.argv[1::]:
  98.         if sprite_file[-4::].casefold() == ".stb":
  99.             # Convert STB file to humanly readable text file
  100.             output_file = sprite_file + ".txt"
  101.             if not os.path.exists(output_file):
  102.                 STB(sprite_file).write_text(output_file)
  103.        
  104.         else:
  105.             # Convert sprite text file to STB file
  106.             output_file = sprite_file + ".stb"
  107.             if not os.path.exists(output_file):
  108.                 STB(sprite_file).write(output_file)
  109.  
Add Comment
Please, Sign In to add comment