Advertisement
Zoinkity

DLparse from Aidyn's Chronicles dumper

Sep 16th, 2015
376
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.83 KB | None | 0 0
  1. def DLparse(pos, imgs, vbnks, data):
  2.     """Parses a display list, generating a list of
  3.    faces and material usage.
  4.    Accepts [pos]ition of DL in [data],
  5.        [imgs] should be a list of materials or a single material ID
  6.        [vbnks] should be a list of base offsets to each vtx bank
  7.  
  8.    Returned list is 4 entries:
  9.        v1, v2, v3, mtl
  10.        (note: untextured surfaces are always mtl0,
  11.            so use 1+ for mtls.)"""
  12.     faces = list()        # faces output
  13.     vtxs  = list()        # faces output
  14.     class face:
  15.         def __init__(self, v1, v2, v3, m):
  16.             self.v1  = v1
  17.             self.v2  = v2
  18.             self.v3  = v3
  19.             self.mtl=m
  20.         def __repr__(self):
  21.             return "face({v1}, {v2}, {v3}, {mtl})".format_map(self.__dict__)
  22.         def __str__(self):
  23.             return "face: {v1}, {v2}, {v3}, material {mtl}".format_map(self.__dict__)
  24.         def __iter__(self):
  25.             """For easy testing of vertex indicies."""
  26.             yield self.v1
  27.             yield self.v2
  28.             yield self.v3
  29.  
  30.     class vtbl:
  31.         def __init__(self, bank, base, num):
  32.             self.bank = bank
  33.             self.base = base
  34.             self.num  = num
  35.         def __repr__(self):
  36.             return "vtbl(0x{bank:X}, 0x{base:X}, {num})".format_map(self.__dict__)
  37.         def __str__(self):
  38.             return "vertex table: {num} entries at offset 0x{base:X} in bank at 0x{bank:X}".format_map(self.__dict__)
  39.  
  40. ##    if isinstance(imgs, int):
  41. ##        imgs = (0, imgs,)
  42.     vtx_i = 0   # acts as a base offset for vertices
  43.     mtl   = 1
  44.     fg, bg = (0, 0, 0, 0), (0, 0, 0, 0) # primary and enviroment color, respectively
  45.     # Breaking down and replacing ultra-efficient ranges with a static buffer.
  46.     vtx   = list(range(-0x80, 0, 1))
  47.     depth = list()
  48.     n = 0
  49.     while True:
  50.         t = data[pos]
  51.         if t == 1:   # vtx list
  52.             bank = data[pos+4]
  53.             ## AIDYN: bank E for culling, A for drawing.  Only push matrix A for now
  54.             if bank==14:
  55.                 pos+=8
  56.                 continue
  57.             vtx_i = int.from_bytes(data[pos+5:pos+8], byteorder='big')
  58.             # Fun part: size of data isn't the same as #loaded!
  59.             vn = int.from_bytes(data[pos+1:pos+3], byteorder='big')
  60.             vn>>=4
  61.             vo = int.from_bytes(data[pos+2:pos+4], byteorder='big')
  62.             vo>>=1
  63.             vo&=0x7F
  64.             dv = vo-vn
  65.             vtx[vo-vn:vo] = range(n, n+vn)
  66. ##            vtxs.append(vtbl(vbnks[bank], vtx_i, vn))
  67.             n+=vn
  68.             s = vbnks[bank]+vtx_i
  69.             vn<<=4
  70.             for i in range(s, s+vn, 16):
  71.                 vtxs.append(data[i:i+16])
  72.         elif t == 2:    # modify vtx    TODO: not sure how to handle yet
  73.             # Quick note: these normally occur after the RSP loads a vertex.
  74.             # What that means for you is normals can't be modified since lighting has already been calc'd
  75.             #   and texture coordinates have already been scaled.
  76.             if data[pos+1]==0x14:
  77.                 # Unfortunately, when texture mapping is changed it you need to flag this
  78.                 #   or otherwise you'll double-calc it since we're computing everything afterward.
  79.                 # Make altered texture coords a bytearray, then test with isinstance()
  80.                 #   to determine if it needs to change later.
  81.                 i = int.from_bytes(data[pos+2:pos+4], byteorder='big')>>1
  82.                 v = bytearray(vtxs[vtx[i]])
  83.                 v[8:12] = data[pos+4:pos+8]
  84.                 vtxs.append(v)
  85.                 vtx[i] = n
  86.                 n+=1
  87.             else:
  88.                 # Apply different matrix conversion to force merging with different part.
  89.                 print("02{:02X} @ 0x{:X}".format(data[pos+1], pos))
  90.         elif t == 3:    # cull DL, effectively a bounding box
  91.             ## TODO: ignore for now.  Draws a box from current 8 vtxs in culling vtx list.
  92.             # bank = data[pos+3]
  93.             pass
  94.         elif t in (5, 6):   # tri-1 and tri-2
  95.             if any(data[pos+1:pos+3]):
  96.                 x, y, z = data[pos+1]>>1, data[pos+2]>>1, data[pos+3]>>1
  97.                 x, y, z = vtx[x], vtx[y], vtx[z]
  98.                 if x<0 or y<0 or z<0:
  99.                     raise IndexError("unregistered vertex: pos 0x{:X}, face {:d} - {}.".format(pos, len(faces), (x,y,z)))
  100.                 faces.append(face(x, y, z, mtl))
  101.             if any(data[pos+5:pos+7]):
  102.                 x, y, z = data[pos+5]>>1, data[pos+6]>>1, data[pos+7]>>1
  103.                 x, y, z = vtx[x], vtx[y], vtx[z]
  104.                 if x<0 or y<0 or z<0:
  105.                     raise IndexError("unregistered vertex: pos 0x{:X}, face {:d} - {}.".format(pos, len(faces), (x,y,z)))
  106.                 faces.append(face(x, y, z, mtl))
  107. ##        elif t==0xC0:   # image declaration
  108. ##            m2 = (int.from_bytes(data[pos+5:pos+7], byteorder='big')>>4) & 0xFFF
  109. ##            m1 = int.from_bytes(data[pos+6:pos+8], byteorder='big') & 0xFFF
  110. ##            if m2>0:    # prefer the LOD replacement image
  111. ##                m1 = m2
  112. ##            mtl = imgTbl.index(m1, imgs)
  113. ##        elif t==0xE7:   # pipesync
  114. ##            # syncs occur before any setting changes, so probably a good indicator for mtl change
  115. ##            mtl = -1
  116.         elif t==0xDE:   # branchDL
  117.             depth.append(pos)
  118.             pos = int.from_bytes(data[pos+4:pos+8], byteorder='big') - conv
  119.             continue
  120.         elif t==0xDF:   # endDL
  121.             if len(depth)<=0:
  122.                 break
  123.             pos = depth.pop()
  124.         elif t==0xFA:
  125.             fg = (data[pos+4], data[pos+5], data[pos+6], data[pos+7])
  126.         elif t==0xFB:
  127.             bg = (data[pos+4], data[pos+5], data[pos+6], data[pos+7])
  128.         # advance to next op
  129.         pos+=8
  130.     # return the faces list
  131.     return faces, vtxs
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement