Cosmetics
[dormin.git] / reeng / nmo.py
blob712667b1e88e986eaeec2aa53c7487885f72e7e4
1 #!/usr/bin/env python
2 import xff2, sys, math
3 from struct import unpack
5 def cstr (s, p):
6 return s[p:p+s[p:].find ("\x00")]
8 class SRF:
9 def __init__ (self, ropos, pos, n, data):
10 self.n = n
11 self.ropos = ropos
12 spos = pos + n * 288
13 self.spos = spos
14 srf = data[spos:spos+288]
15 if srf[:4] <> "SRF\x00":
16 raise "sourface %d at %08x, bad signature" % (n, spos + ropos), srf[:4]
18 self.D04_10 = unpack ("<3I", srf[4:0x10])
19 self.tricount = self.D04_10[0]
20 self.stripcount = self.D04_10[1]
21 self.nameoff = self.D04_10[2]
22 self.hdr1 = []
23 for i in range (3):
24 stru = unpack ("<4BfII", srf[0x10+i*16:0x10+(i+1)*16])
25 self.hdr1.append (stru)
27 self.hdr2 = unpack ("<I2f5I", srf[0x40:0x60])
28 self.hdr3 = unpack ("<48I", srf[0x60:288])
29 self.rodata = data
31 def pr (self):
32 print " [%d] %s (%08x)" % (self.n, cstr (self.rodata, self.nameoff),
33 self.ropos + self.spos)
34 print " triangle count %d" % self.tricount
35 print " strip count %d" % self.stripcount
36 # print " %s" % cstr (self.rodata, self.D04_10[2])
37 # print " %08x %d" % (self.D04_10[2], self.D04_10[2])
38 # print " | %08x %d" % (self.D04_10[2] + self.ropos, self.D04_10[2] + self.ropos)
40 i = 0
41 for stru in self.hdr1:
42 print " Stru %d" % i
43 print " %d, %d, %d, %d" % (stru[0], stru[1], stru[2], stru[3])
44 print " %f" % stru[4]
45 print " %08x %d" % (stru[5], stru[5])
46 print " %08x %d" % (stru[6], stru[6])
47 i += 1
49 j = 0
50 print " Hdr2"
51 for v in self.hdr2:
52 if j == 1 or j == 2:
53 print " [%d] % f" % (j, v)
54 else:
55 print " [%d] %08x %d" % (j, v, v)
56 j += 1
58 if 1==1:
59 print " Hdr3"
60 j = 0
61 for v in self.hdr3:
62 print " [%d] %08x %d" % (j, v, v)
63 j += 1
65 class HDR3:
66 def __init__ (self, pos, data):
67 buf = data[pos:pos+32]
68 D = unpack ("<8I", buf)
69 self.size = D[0]
70 self.unk_D_04 = D[1]
71 self.surf = D[2]
72 self.unk_D_0C = D[3]
73 self.offs = D[4]
74 self.tricount = D[5]
75 self.stripcount = D[6]
76 self.unk_D_1C = D[7]
78 def pr (self, ropos):
79 print " at %08x size %d (ends at %08x)" % (self.offs + ropos,
80 self.size,
81 self.offs + self.size + ropos)
82 print " surface %d" % self.surf
83 print " triangle count %d" % self.tricount
84 print " strip count %d" % self.stripcount
85 if self.unk_D_04:
86 print " !!! unknown at 04 = %08x %d" % (self.unk_D_04, self.unk_D_04)
87 print " unknown at 0C = %08x %d" % (self.unk_D_0C, self.unk_D_0C)
88 if self.unk_D_1C:
89 print " !!! unknown at 1c = %08x %d" % (self.unk_D_1C, self.unk_D_1C)
91 class NMO:
92 def geom (self, ropos, count):
93 pos = 0
94 for surf in range (count):
95 print
96 print "Surface %d %08x:" % (surf, pos + ropos)
98 buf = self.data
99 bytes = unpack ("<12B", buf[:12])
100 if bytes[2] <> 0 or bytes[6] <> 0 or bytes[10] <> 0:
101 raise "Unexpected sequence at %08x %s" % (ropos + pos,
102 buf[:12].encode ("hex"))
103 for b in bytes:
104 print " %03x" % b,
105 print
106 for b in bytes:
107 print " %3d" % b,
108 print
110 pos += 12
112 simple = True
113 while simple:
114 print
115 print " %08x:" % (pos + ropos)
116 bytes = unpack ("<4B", buf[pos:pos+4])
118 index = bytes[0]
119 mask = bytes[1]
120 count = bytes[2]
121 kind = bytes[3]
123 if kind == 0x6c:
124 print "="*80
125 print " %d %02x count=%d %02x" % (index, mask, count, kind),
126 if kind >> 4 <> 0 and mask <> 0x80:
127 print " (NON 80 MASK)"
128 else:
129 print
131 pos += 4
132 if kind == 0x6c:
133 for i in range (count):
134 if index == 0:
135 t = unpack ("<BBH3I",buf[pos:pos+16])
136 print " (%04x(%d) %02x %d)" % (t[2], t[2],
137 t[1], t[0])
138 print " %08x %d" % (t[3], t[3])
139 print " %08x %d" % (t[4], t[4])
140 print " %08x %d" % (t[5], t[5])
141 pos += 16
142 else:
143 t = unpack ("<3fI",buf[pos:pos+16])
144 print " | %f" % t[0]
145 print " | %f" % t[1]
146 print " | %f" % t[2]
147 print " %d" % (t[3])
148 pos += 16
150 elif kind == 0x68:
151 for i in range (count):
152 F = unpack ("<3f", buf[pos:pos+12])
153 if index == 1:
154 print " v % f, % f, % f" % (F[0], F[1], F[2])
155 else:
156 Fn = math.sqrt (F[0]*F[0] + F[1]*F[1] + F[2]*F[2])
157 print " n % f, % f, % f -> %f" % (F[0], F[1], F[2], Fn)
158 pos += 12
160 elif kind == 0x6d:
161 for i in range (count):
162 h = unpack ("<4h", buf[pos:pos+8])
163 H = unpack ("<4H", buf[pos:pos+8])
164 #print buf[pos:pos+8].encode ("hex")
165 print " %04x %04x %04x %04x | % 5d % 5d % 5d % 5d" % (H[0], H[1],
166 H[2], H[3],
167 h[0], h[1],
168 h[2], h[3])
169 pos += 8
171 elif kind == 0x05:
172 if mask != 0:
173 raise "5 with non zero mask?"
175 elif kind == 0x6e:
176 for i in range (count):
177 B = unpack ("<4B", buf[pos:pos+4])
178 print " %02x %02x %02x %02x (%3d, %3d, %3d, %3d)" % (B[0], B[1],
179 B[2], B[3],
180 B[0], B[1],
181 B[2], B[3])
182 pos += 4
184 elif kind == 0x17:
185 if mask <> 0 or count <> 0 or index <> 0:
186 raise "0x17 with invalid stuff"
188 elif kind == 0x65:
189 for i in range (count):
190 h = unpack ("<2h", buf[pos:pos+4])
191 H = unpack ("<2H", buf[pos:pos+4])
192 print " %04x %04x | % 5d % 5d" % (H[0], H[1], h[0], h[1])
193 pos += 4
195 elif kind == 0x00 and index == 0x00 and mask == 0x00 and count == 0x00:
196 pos = (pos + 15) & ~15
197 print " POS %08x" % (pos+ropos)
198 simple = False
200 else:
201 raise "Unknown kind", hex (kind)
203 def __init__ (self, file, xff):
204 rodata = xff.sections[1]
205 self.rodata = rodata
206 file.seek (rodata[1][7])
207 data = file.read (rodata[1][2])
208 self.data = data
209 hdr = data[xff.off_sign:][:0x80]
210 if hdr[:4] <> "NMO\x00":
211 raise "bad signature", hdr[:4]
213 self.D7 = unpack ("<7I", hdr[4:0x20])
214 self.F4 = unpack ("<4f", hdr[0x20:0x30])
215 self.D4 = unpack ("<4I", hdr[0x20:0x30])
217 self.hdrs = []
218 for i in range (5):
219 s = hdr[0x30+i*0x10:0x30+(i+1)*0x10]
220 u = unpack ("<4I", s)
221 self.hdrs.append (u)
223 self.data0 = data[self.hdrs[0][0]:self.hdrs[0][0]+144]
225 self.texs = []
226 for i in range (self.hdrs[1][1]):
227 pos = self.hdrs[1][0] + i*32
228 tdata = data[pos:pos+32]
229 if tdata[:4] <> "TEX\x00":
230 raise "bad tex object %d at %08x" % (i, pos), tdata[:4]
231 stru = unpack ("<5I2H2H", tdata[4:0x20])
232 nameoff = stru[0]
233 name = cstr (data, nameoff)
234 tex = (name,) + stru[1:]
235 self.texs.append (tex)
237 self.srfs = []
238 for i in range (self.hdrs[2][1]):
239 self.srfs.append (SRF (rodata[1][7], self.hdrs[2][0], i, data))
241 self.hdr3 = []
242 for i in range (self.hdrs[3][1]):
243 pos = self.hdrs[3][0] + i*32
244 # stru = unpack ("<8I", data[pos:pos+32])
245 self.hdr3.append (HDR3 (pos, data))
247 try:
248 self.geom (rodata[1][7], self.hdrs[3][1] )
249 except:
250 print "Unexpected error:", sys.exc_info()
251 pass
253 def pr (self):
254 i = 0
255 for d in self.D7:
256 print " [%d] %08x %d" % (i, d, d)
257 i = i + 1
259 i = 0
260 for f in self.F4:
261 print " [%d] %08x % f" % (i, self.D4[i], f)
262 i = i + 1
264 for i in range (5):
265 u = self.hdrs[i]
266 print "[%d]" % i
267 print " %08x (%08x) offset" % (u[0], u[0] + self.rodata[1][7])
268 print " %08x %d count" % (u[1], u[1])
269 print " %08x" % u[2]
270 print " %08x" % u[3]
271 #if i == 0:
272 # print " %08x" % (u[0] + 144)
273 if i == 4:
274 print "Name = ",
275 print cstr (self.data, u[0])
277 print "Header 3"
278 for i in range (len (self.hdr3)):
279 hdr3 = self.hdr3[i]
280 print " [%d]" % i,
281 hdr3.pr (self.rodata[1][7])
282 ## v = self.hdr3[i]
283 ## for j in range (len (v)):
284 ## vv = v[j]
285 ## if j == 4:
286 ## vvv = vv + self.rodata[1][7]
287 ## print " [%d] %08x %d %08x %d" % (j, vv, vv, vvv, vvv)
288 ## elif j == 0:
289 ## vvv = v[4] + vv + self.rodata[1][7]
290 ## print " [%d] %08x %d %08x %d" % (j, vv, vv, vvv, vvv)
291 ## else:
292 ## print " [%d] %08x %d" % (j, vv, vv)
294 print "Textures"
295 nr = 0
296 for tex in self.texs:
297 print " [%4d] %s" % (nr, tex[0])
298 for i in range (6):
299 print " %08x %d" % (tex[i+1], tex[i+1])
300 print " %dx%d" % (tex[7], tex[8])
301 nr = nr + 1
303 print "Sourfaces"
304 for srf in self.srfs:
305 srf.pr ()
306 print
308 print sys.argv[1]
309 f = open (sys.argv[1], "rb")
310 x = xff2.XFF (f, 0)
311 n = NMO (f, x)
312 n.pr ()
313 #x.pr (False)
314 #rodata = x.sections[1]