Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- def DLparse(pos, imgs, vbnks, data):
- """Parses a display list, generating a list of
- faces and material usage.
- Accepts [pos]ition of DL in [data],
- [imgs] should be a list of materials or a single material ID
- [vbnks] should be a list of base offsets to each vtx bank
- Returned list is 4 entries:
- v1, v2, v3, mtl
- (note: untextured surfaces are always mtl0,
- so use 1+ for mtls.)"""
- faces = list() # faces output
- vtxs = list() # faces output
- class face:
- def __init__(self, v1, v2, v3, m):
- self.v1 = v1
- self.v2 = v2
- self.v3 = v3
- self.mtl=m
- def __repr__(self):
- return "face({v1}, {v2}, {v3}, {mtl})".format_map(self.__dict__)
- def __str__(self):
- return "face: {v1}, {v2}, {v3}, material {mtl}".format_map(self.__dict__)
- def __iter__(self):
- """For easy testing of vertex indicies."""
- yield self.v1
- yield self.v2
- yield self.v3
- class vtbl:
- def __init__(self, bank, base, num):
- self.bank = bank
- self.base = base
- self.num = num
- def __repr__(self):
- return "vtbl(0x{bank:X}, 0x{base:X}, {num})".format_map(self.__dict__)
- def __str__(self):
- return "vertex table: {num} entries at offset 0x{base:X} in bank at 0x{bank:X}".format_map(self.__dict__)
- ## if isinstance(imgs, int):
- ## imgs = (0, imgs,)
- vtx_i = 0 # acts as a base offset for vertices
- mtl = 1
- fg, bg = (0, 0, 0, 0), (0, 0, 0, 0) # primary and enviroment color, respectively
- # Breaking down and replacing ultra-efficient ranges with a static buffer.
- vtx = list(range(-0x80, 0, 1))
- depth = list()
- n = 0
- while True:
- t = data[pos]
- if t == 1: # vtx list
- bank = data[pos+4]
- ## AIDYN: bank E for culling, A for drawing. Only push matrix A for now
- if bank==14:
- pos+=8
- continue
- vtx_i = int.from_bytes(data[pos+5:pos+8], byteorder='big')
- # Fun part: size of data isn't the same as #loaded!
- vn = int.from_bytes(data[pos+1:pos+3], byteorder='big')
- vn>>=4
- vo = int.from_bytes(data[pos+2:pos+4], byteorder='big')
- vo>>=1
- vo&=0x7F
- dv = vo-vn
- vtx[vo-vn:vo] = range(n, n+vn)
- ## vtxs.append(vtbl(vbnks[bank], vtx_i, vn))
- n+=vn
- s = vbnks[bank]+vtx_i
- vn<<=4
- for i in range(s, s+vn, 16):
- vtxs.append(data[i:i+16])
- elif t == 2: # modify vtx TODO: not sure how to handle yet
- # Quick note: these normally occur after the RSP loads a vertex.
- # What that means for you is normals can't be modified since lighting has already been calc'd
- # and texture coordinates have already been scaled.
- if data[pos+1]==0x14:
- # Unfortunately, when texture mapping is changed it you need to flag this
- # or otherwise you'll double-calc it since we're computing everything afterward.
- # Make altered texture coords a bytearray, then test with isinstance()
- # to determine if it needs to change later.
- i = int.from_bytes(data[pos+2:pos+4], byteorder='big')>>1
- v = bytearray(vtxs[vtx[i]])
- v[8:12] = data[pos+4:pos+8]
- vtxs.append(v)
- vtx[i] = n
- n+=1
- else:
- # Apply different matrix conversion to force merging with different part.
- print("02{:02X} @ 0x{:X}".format(data[pos+1], pos))
- elif t == 3: # cull DL, effectively a bounding box
- ## TODO: ignore for now. Draws a box from current 8 vtxs in culling vtx list.
- # bank = data[pos+3]
- pass
- elif t in (5, 6): # tri-1 and tri-2
- if any(data[pos+1:pos+3]):
- x, y, z = data[pos+1]>>1, data[pos+2]>>1, data[pos+3]>>1
- x, y, z = vtx[x], vtx[y], vtx[z]
- if x<0 or y<0 or z<0:
- raise IndexError("unregistered vertex: pos 0x{:X}, face {:d} - {}.".format(pos, len(faces), (x,y,z)))
- faces.append(face(x, y, z, mtl))
- if any(data[pos+5:pos+7]):
- x, y, z = data[pos+5]>>1, data[pos+6]>>1, data[pos+7]>>1
- x, y, z = vtx[x], vtx[y], vtx[z]
- if x<0 or y<0 or z<0:
- raise IndexError("unregistered vertex: pos 0x{:X}, face {:d} - {}.".format(pos, len(faces), (x,y,z)))
- faces.append(face(x, y, z, mtl))
- ## elif t==0xC0: # image declaration
- ## m2 = (int.from_bytes(data[pos+5:pos+7], byteorder='big')>>4) & 0xFFF
- ## m1 = int.from_bytes(data[pos+6:pos+8], byteorder='big') & 0xFFF
- ## if m2>0: # prefer the LOD replacement image
- ## m1 = m2
- ## mtl = imgTbl.index(m1, imgs)
- ## elif t==0xE7: # pipesync
- ## # syncs occur before any setting changes, so probably a good indicator for mtl change
- ## mtl = -1
- elif t==0xDE: # branchDL
- depth.append(pos)
- pos = int.from_bytes(data[pos+4:pos+8], byteorder='big') - conv
- continue
- elif t==0xDF: # endDL
- if len(depth)<=0:
- break
- pos = depth.pop()
- elif t==0xFA:
- fg = (data[pos+4], data[pos+5], data[pos+6], data[pos+7])
- elif t==0xFB:
- bg = (data[pos+4], data[pos+5], data[pos+6], data[pos+7])
- # advance to next op
- pos+=8
- # return the faces list
- return faces, vtxs
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement