00001
00002
00003
00004
00005
00006 import sys,struct,string
00007
00008 class _Typelist:
00009 def __init__(self, d):
00010 self.map = d
00011 for k,v in d.items():
00012 setattr(self, v, k)
00013
00014 _gnames = {
00015 0: "MECH",
00016 1: "DEBUG",
00017 2: "MECHREP",
00018 3: "MAP",
00019 4: "CHARGEN",
00020 5: "AUTO",
00021 6: "TURRET",
00022 7: "CUSTOM",
00023 8: "SCEN",
00024 9: "SSIDE",
00025 10: "SSOBJ",
00026 11: "SSINS",
00027 12: "SSEXT",
00028 13: "FMAP",
00029 14: "FMAPBLOCK",
00030 15: "FLOC",
00031 16: "FCHAR",
00032 17: "FOBJ",
00033 18: "FMOD",
00034
00035
00036 }
00037
00038 gtypes = _Typelist(_gnames)
00039
00040 NUM_MAPOBJ = 10
00041 DYNAMIC_MAGIC = 42
00042 MAPFLAG_MAPO = 1
00043 MAPOBJSTART_MAGICNUM = 27
00044 MAPOBJEND_MAGICNUM = 39
00045 TYPE_BITS = 8
00046
00047 class HCodeDB:
00048 def __init__(self, fp=None):
00049 self.data = []
00050 self.db = {}
00051 if fp:
00052 self.fp = fp
00053 self.readdb()
00054
00055 def hcodeobj(self, key, type, size, data):
00056 if type == gtypes.MECH:
00057 return MECHObject(key, type, size, data)
00058 elif type == gtypes.MAP:
00059 return MAPObject(key, type, size, data)
00060 else:
00061 return HCodeObject(key, type, size, data)
00062
00063 def readdb(self):
00064
00065
00066
00067
00068
00069 self.version = ord(self.fp.read(1))
00070 keydata = self.fp.read(4)
00071 while keydata and len(keydata) == 4:
00072 key = struct.unpack("=i", keydata)[0]
00073 if key < 0:
00074 break
00075 header = self.fp.read(3)
00076 type, size = struct.unpack("=bH", header)
00077 data = self.fp.read(size)
00078
00079
00080
00081
00082
00083 obj = self.hcodeobj(key, type, size, data)
00084 self.data.append(obj)
00085 self.db[key] = obj
00086 keydata = self.fp.read(4)
00087
00088 sys.stderr.write("Done loading xcode tree: %d\n"%self.fp.tell())
00089
00090
00091 for meth in ("load_update1", "load_update2",
00092 "load_update3", "load_update4"):
00093 for obj in self.data:
00094 if hasattr(obj, meth):
00095 getattr(obj,meth)(self.fp)
00096 sys.stderr.write("Done pass " + meth + ": %d\n"%self.fp.tell())
00097
00098
00099
00100
00101 class HCodeObject:
00102 def __init__(self, key, type, size, data):
00103 self.key = key
00104 self.type = type
00105 self.size = size
00106 self.data = data
00107 def __repr__(self):
00108 return "<HCodeObject key %s type %s>"%(self.key, gtypes.map[self.type])
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 class MECHObject(HCodeObject):
00274 def __init__(self, key, type, size, data):
00275 self.key = key
00276 self.type = type
00277
00278 header_format = "iii2sb" + 4*3*"L" + 16*"16s" + "16i" + "16i"
00279 critslot_format = "HbHb0H"
00280 section_format = "BBBBBBbbb" + critslot_format*12
00281 ud_format = ("31s 15s bbiHbbb" + section_format*8 +
00282 "bbiifbbbii8i0H" )
00283 pd_format = "ibHbbHibHHHHHfffii4i3i0H"
00284 rd_format = ("ffff HbHHfHHfffHHHHH bbHb iiiiii " "cffffiii"
00285 "ci2bbiHHiiiiii"
00286 "iiiiiibibiiHHiifiiibbHiiii7i0H")
00287
00288 self.format = ("@" + header_format + ud_format +
00289 pd_format + rd_format)
00290
00291 self.data = data
00292 self.parsedata(data, size)
00293
00294 def parsedata(self, data, size):
00295
00296 class _Dummy:
00297 pass
00298
00299 def _cull(s):
00300 return s[:string.find(s, "\000")]
00301
00302 pdata = struct.unpack(self.format, data)
00303 (self.mynum, self.mapnumber, self.mapindex, self.ID,
00304 self.brief), pdata = pdata[:5], pdata[5:]
00305 self.tic = []
00306 for i in range(4):
00307 self.tic.append(pdata[:3])
00308 pdata = pdata[3:]
00309
00310 self.chantitles, pdata = list(pdata[:16]), pdata[16:]
00311 for i in range(16):
00312 self.chantitles[i] = _cull(self.chantitles[i])
00313 self.freqs, pdata = pdata[:16], pdata[16:]
00314 self.freqmodes, pdata = pdata[:16], pdata[16:]
00315
00316 ud = _Dummy()
00317 (ud.mech_name, ud.mech_type, type, move, tons, radio_range,
00318 tac_range, lrs_range, scan_range), pdata = pdata[:9], pdata[9:]
00319 ud.mech_name = _cull(ud.mech_name)
00320 ud.mech_type = _cull(ud.mech_type)
00321 ud.sections = []
00322 for i in range(8):
00323 section = _Dummy()
00324 (section.armor, section.internal, section.rear,
00325 section.armor_orig, section.internal_orig,
00326 section.rear_orig, section.basetohit, section.config,
00327 section.recycle), pdata = pdata[:9], pdata[9:]
00328 section.crits = []
00329 for i in range(12):
00330 crit = _Dummy()
00331 (crit.type, crit.data, crit.mode, crit.brand
00332 ), pdata = pdata[:4], pdata[4:]
00333 section.crits.append(crit)
00334 ud.sections.append(section)
00335 (ud.si, ud.si_orig, ud.fuel, ud.fuel_orig, ud.maxspeed,
00336 ud.computer, ud.radio, ud.radioinfo, ud.mechbv, ud.cargospace,
00337 ), pdata = pdata[:10], pdata[10:]
00338 ud.unused, pdata = pdata[:8], pdata[8:]
00339 self.ud = ud
00340
00341 pd = _Dummy()
00342 (pd.pilot, pd.pilotstatus, pd.hexes_walked, pd.terrain,
00343 pd.elev, pd.facing, pd.master_c3_node, pd.team, pd.x,
00344 pd.y, pd.z, pd.last_x, pd.last_y, pd.fx, pd.fy, pd.fz,
00345 pd.unusable_arcs, pd.stall), pdata = pdata[:18], pdata[18:]
00346 pd.bays, pdata = pdata[:4], pdata[4:]
00347 pd.turrets, pdata = pdata[:4], pdata[4:]
00348 self.pd = pd
00349
00350 rd = _Dummy()
00351 (rd.startfx, rd.startfy, rd.startfz, rd.endfz, rd.jumplength,
00352 rd.jumptop, rd.goingx, rd.goingy, rd.verticalspeed,
00353 rd.desiredfacing, rd.angle, rd.speed, rd.desired_speed,
00354 rd.jumpspeed, rd.jumpheading, rd.targx, rd.targy, rd.targz,
00355 rd.turretfacing, rd.aim, rd.pilotskillbase, rd.turndamage,
00356 rd.basetohit, rd.chgtarget, rd.dfatarget, rd.target,
00357 rd.swarming, rd.carrying, rd.spotter, rd.engineheat, rd.heat,
00358 rd.weapheat, rd.plus_heat, rd.minus_heat, rd.critstatus,
00359 rd.status, rd.specials, rd.masc_value, rd.last_weapon_recycle,
00360 rd.sensor, rd.fire_adjustment, rd.cargo_weight, rd.lateral,
00361 rd.num_seen, rd.lastrndu, rd.rnd, rd.last_ds_msg, rd.boom_start,
00362 rd.maxfuel, rd.lastused, rd.cocoon, rd.commconv,
00363 rd.commconv_last, rd.onumsinks, rd.disabled_hs,
00364 rd.autopilot_num, rd.aim_type, rd.heatboom_last, rd.vis_mod,
00365 rd.sspin, rd.can_see, rd.lx, rd.ly, rd.row, rd.rcw, rd.rspd,
00366 rd.erat, rd.per, rd.wxf, rd.chargetimer, rd.chargedist,
00367 rd.mech_prefs, rd.last_startup, rd.specialstatus,
00368 rd.tankcritstatus, rd.specials2), pdata = pdata[:76],pdata[76:]
00369
00370 rd.unused, pdata = pdata[:7], pdata[7:]
00371 self.rd = rd
00372
00373 if pdata:
00374 sys.stderr.write("pdata left! %s\n"%(pdata,))
00375 sys.stderr.write("length of data: %s\n"%size)
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 class MAPObject(HCodeObject):
00410 def __init__(self, key, type, size, data):
00411 self.key = key
00412 self.type = type
00413
00414 self.format = "@ii31sHHbBHbbHbHHb10iHHibBiiiHH"
00415 self.parsedata(data, size)
00416
00417 def parsedata(self, data, size):
00418 csize = struct.calcsize(self.format)
00419 if (size <> csize):
00420 sys.stderr.write("Wrong size: %d vs %d"%(size, csize))
00421 if size < csize:
00422 data += "\0"*(csize - size)
00423 else:
00424 data = data[:csize]
00425
00426 pdata = list(struct.unpack(self.format, data))
00427 (self.mynum, x, self.name, self.width, self.height,
00428 self.temp, self.grav, self.cloudbase, self.unused, self.vis,
00429 self.maxvis, self.light, self.winddir, self.windspeed,
00430 self.flags), pdata = pdata[:15], pdata[15:]
00431
00432
00433 pdata = pdata[10:]
00434
00435 (self.cf, self.maxcf, self.onmap, self.buildflag,
00436 self.first_free, x, x, x,
00437 self.moves, self.movemod) = pdata
00438
00439 def load_update1(self, fp):
00440 self.map = []
00441 self.losinfo = []
00442 num = self.first_free
00443
00444 if num:
00445 fmt = "@" + "i" * num
00446 self.mechsonmap = _unpack(fmt, fp)
00447 fmt = "@" + "b" * num
00448 self.mechflags = _unpack(fmt, fp)
00449 fmt = "@" + "H" * num
00450 for x in range(num):
00451 self.losinfo.append(_unpack(fmt, fp))
00452 else:
00453 self.mechsonmap = []
00454 self.mapobj = []
00455
00456 magic = ord(fp.read(1))
00457 if magic <> DYNAMIC_MAGIC:
00458 sys.stderr.write("Did not find DYNAMIC_MAGIC for #%d\n"%self.mynum)
00459 sys.stderr.write("Wanted %d, got %d\n"%(DYNAMIC_MAGIC, magic))
00460 sys.exit(1)
00461
00462 if self.flags & MAPFLAG_MAPO:
00463 self.load_mapobj(fp)
00464
00465 def load_mapobj(self, fp):
00466 magic = ord(fp.read(1))
00467 if magic <> MAPOBJSTART_MAGICNUM:
00468 sys.stderr.write("Did not find mapobjstartmagic for #%d\n"%self.mynum)
00469 sys.stderr.write("Wanted %d, got %d\n"%(MAPOBJSTART_MAGICNUM, magic))
00470
00471 self.mapobj = []
00472 for i in range(NUM_MAPOBJ):
00473 self.mapobj.append([])
00474
00475 nextbyte = ord(fp.read(1))
00476 while nextbyte:
00477 if nextbyte - 1 == TYPE_BITS:
00478 self.load_bits(fp)
00479 else:
00480 self.mapobj[nextbyte - 1].append(MapobjObject(fp))
00481 nextbyte = ord(fp.read(1))
00482 magic = ord(fp.read(1))
00483 if magic <> MAPOBJEND_MAGICNUM:
00484 sys.stderr.write("no mapobjend found for #%d!\n")
00485 sys.stderr.write("Wanted %d, got %d\n"%(MAPOBJEND_MAGICNUM, magic))
00486
00487 def load_bits(self, fp):
00488
00489 self.mapbits = []
00490 fmt = "@" + "i"*self.height
00491 foo = _unpack(fmt, fp)
00492 fmt = "@" + "B"*(self.width / 4 + ((self.width % 4) and 1 or 0))
00493 for x in foo:
00494 if x:
00495 self.mapbits.append(_unpack(fmt, fp))
00496 else:
00497 self.mapbits.append([])
00498
00499
00500 class MapobjObject:
00501 def __init__(self, fp):
00502 fmt = "@HHiccHii"
00503 (self.x, self.y, self.obj, self.type, self.datac,
00504 self.datas, self.datai, x) = _unpack(fmt, fp)
00505
00506
00507 def _unpack(fmt, fp):
00508 return list(struct.unpack(fmt, fp.read(struct.calcsize(fmt))))
00509
00510
00511 if __name__ == "__main__":
00512 if len(sys.argv) <> 2:
00513 print "Usage: python -i hcodedb.py <hcodedbfile>"
00514 sys.exit()
00515
00516 db = HCodeDB(open(sys.argv[1]))
00517
00518