Advertisement
Thurler

Labyrinth 2 spell dump script

Nov 23rd, 2021
1,010
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.69 KB | None | 0 0
  1. import pefile
  2.  
  3. def skipPastSequence(f, target, bufsize=0):
  4.   match_index = 0
  5.   buf = []
  6.   resbuf = []
  7.   while (match_index < len(target)):
  8.     char = chr(int.from_bytes(f.read(1), "little"))
  9.     if bufsize > 0:
  10.       if len(buf) == bufsize:
  11.         buf.pop(0)
  12.       buf.append(char)
  13.     if char == target[match_index]:
  14.       match_index += 1
  15.     else:
  16.       if bufsize > 0:
  17.         resbuf = buf[::]
  18.       match_index = 0
  19.   return "".join(resbuf) if bufsize > 0 else None
  20.  
  21. def readString(offset):
  22.   offset -= 0x400000
  23.   for s in sections:
  24.     if offset >= s['vaddr'] and offset < s['vend']:
  25.       offset = offset - s['vaddr'] + s['paddr']
  26.       break
  27.   buf = ''
  28.   while True:
  29.     if (raw[offset] == 0):
  30.       break
  31.     buf += chr(raw[offset])
  32.     offset += 1
  33.   return buf
  34.  
  35. def readSpellData(f, o):
  36.   start = ("\x8b\x45\xec\x8b\x4d\x10\x89\x48\x08\x8b\x45\xec\x8b\x48\x08\x8b" +
  37.            "\x55\xec\x8b\x01\x89\x42\x04\x8b\x45\xec\x8b\x4d\x08\x89\x88\x8c" +
  38.            "\x00\x00\x00\x8b\x55\xec\x8b\x45\x0c\x89\x82\x90\x00\x00\x00")
  39.   skipPastSequence(f, start)
  40.   # Read spell name
  41.   f.read(1)
  42.   nameOffset = int.from_bytes(f.read(4), "little")
  43.   name = readString(nameOffset)
  44.   o.write(name + ',')
  45.   # Read targetting mode
  46.   skipPastSequence(f, "\xc7\x80\x98")
  47.   f.read(3)
  48.   targetting = int.from_bytes(f.read(4), "little", signed=True)
  49.   o.write(str(targetting) + ',')
  50.   if (name == "Mononobe's Eighty Sake Cups"):
  51.     # It changes when there are more than 6 cups, ignore that for now
  52.     f.read(71)
  53.   # Read elements
  54.   buf = None
  55.   if (name == "Tradition of Just Rewards"):
  56.     # It changes depending on HP and skills learned, just put all 3 in there tbh
  57.     f.read(220)
  58.     elements = ['MYS', 'SPI', 'DRK']
  59.   else:
  60.     elements = []
  61.     while True:
  62.       buf = list(f.read(7))
  63.       if (buf[5:] == [0xd1, 0xe0]):
  64.         elements += ['WND']
  65.       else:
  66.         buf += list(f.read(1))
  67.         if (buf[5:] == [0x6b, 0xc8, 0x00]):
  68.           elements += ['FIR']
  69.         elif (buf[5:] == [0xc1, 0xe0, 0x00]):
  70.           elements += ['CLD']
  71.         elif (buf[5:] == [0x6b, 0xc8, 0x03]):
  72.           elements += ['NTR']
  73.         elif (buf[5:] == [0xc1, 0xe0, 0x02]):
  74.           elements += ['MYS']
  75.         elif (buf[5:] == [0x6b, 0xc8, 0x05]):
  76.           elements += ['SPI']
  77.         elif (buf[5:] == [0x6b, 0xc8, 0x06]):
  78.           elements += ['DRK']
  79.         elif (buf[5:] == [0x6b, 0xc8, 0x07]):
  80.           elements += ['PHY']
  81.         elif (buf[5:] == [0xc1, 0xe0, 0x03]):
  82.           elements += ['VOI']
  83.         else:
  84.           break
  85.       f.read(14)
  86.   elements = "-".join(elements)
  87.   o.write(elements + ',')
  88.   # Read ATK influence
  89.   if (name == "Youkai Yakuza Kick"):
  90.     # Normal / Skill learned / Reading / Reading + Skill
  91.     f.read(77)
  92.     atk = "150/170/210/230"
  93.   else:
  94.     f.read(1)
  95.     atk = int.from_bytes(f.read(4), "little", signed=True)
  96.   o.write(str(atk) + ',')
  97.   # Read MAG influence
  98.   if (name == "Mari's DIY Novice Border"):
  99.     # Only applies from certain level
  100.     f.read(23)
  101.     mag = -16
  102.   elif (name == "The Count of Monte Cristo" or name == "Musketeer d'Artagnan"):
  103.     # Normal / Reading
  104.     f.read(13)
  105.     mag = "120/140"
  106.   else:
  107.     f.read(9)
  108.     mag = int.from_bytes(f.read(4), "little", signed=True)
  109.   o.write(str(mag) + ',')
  110.   # Read DEF influence
  111.   f.read(9)
  112.   dfe = int.from_bytes(f.read(4), "little", signed=True)
  113.   o.write(str(dfe) + ',')
  114.   # Read MND influence
  115.   f.read(9)
  116.   mnd = int.from_bytes(f.read(4), "little", signed=True)
  117.   o.write(str(mnd) + ',')
  118.   # Read T.DEF influence
  119.   f.read(9)
  120.   tdef = int.from_bytes(f.read(4), "little", signed=True)
  121.   o.write(str(tdef) + ',')
  122.   # Read T.MND influence
  123.   f.read(9)
  124.   tmnd = int.from_bytes(f.read(4), "little", signed=True)
  125.   o.write(str(tmnd) + ',')
  126.   # Read multiplier
  127.   if (name == "Mari's DIY Novice Border"):
  128.     f.read(32)
  129.     multiplier = 100
  130.   elif (name == "Youkai Yakuza Kick"):
  131.     # Normal / Skill learned / Reading / Reading + Skill
  132.     f.read(85)
  133.     multiplier = "150/170/210/230"
  134.   elif (name == "The Count of Monte Cristo" or name == "Musketeer d'Artagnan"):
  135.     # Normal / Reading
  136.     f.read(13)
  137.     multiplier = "120/150"
  138.   else:
  139.     f.read(9)
  140.     multiplier = int.from_bytes(f.read(4), "little", signed=True)
  141.   o.write(str(multiplier) + ',')
  142.   # Read accuracy
  143.   f.read(9)
  144.   accuracy = int.from_bytes(f.read(4), "little", signed=True)
  145.   o.write(str(accuracy) + ',')
  146.   # Read delay
  147.   if (name == "The Count of Monte Cristo" or name == "Musketeer d'Artagnan"):
  148.     # Normal / Reading
  149.     delay = "4000/7000"
  150.   elif (name == "Non-Neumann Systems"):
  151.     # Normal / Reading
  152.     delay = "3000/5500"
  153.   elif (name == "Selfless Love"):
  154.     delay = "5300+(300*SLv)"
  155.   elif (name == "Hourai Elixir"):
  156.     delay = "3400+(300*SLv)"
  157.   elif (name == "Missing Power"):
  158.     delay = "1500+(500*SLv)"
  159.   else:
  160.     f.read(9)
  161.     delay = int.from_bytes(f.read(4), "little", signed=True)
  162.   o.write(str(delay) + ',')
  163.   # Compute power
  164.   if (name == "Youkai Yakuza Kick"):
  165.     power = "/".join([
  166.       str(round((int(a)*int(m)) / 10000, 2)) for a, m in zip(
  167.         atk.split('/'), multiplier.split('/')
  168.       )
  169.     ])
  170.   elif (name == "The Count of Monte Cristo" or name == "Musketeer d'Artagnan"):
  171.     power = "/".join([
  172.       str(round((int(a)*int(m)) / 10000, 2)) for a, m in zip(
  173.         mag.split('/'), multiplier.split('/')
  174.       )
  175.     ])
  176.   else:
  177.     power = (atk + mag + dfe + mnd) * multiplier / 10000
  178.     power = str(round(power, 2))
  179.   o.write(power + ',')
  180.   # Compute piercing power
  181.   if (tdef + tmnd) == 0:
  182.     pierce = '+inf'
  183.   elif (name == "Youkai Yakuza Kick"):
  184.     pierce = "/".join([
  185.       str(round(int(a) / (tdef + tmnd), 2)) for a in atk.split('/')
  186.     ])
  187.   elif (name == "The Count of Monte Cristo" or name == "Musketeer d'Artagnan"):
  188.     pierce = "/".join([
  189.       str(round(int(a) / (tdef + tmnd), 2)) for a in mag.split('/')
  190.     ])
  191.   else:
  192.     pierce = (atk + mag + dfe + mnd) / (tdef + tmnd)
  193.     pierce = str(round(pierce, 2))
  194.   o.write(pierce + '\n')
  195.   return name
  196.  
  197. raw = None
  198. sections = []
  199. with open("laby2_1107e.exe", 'rb') as f:
  200.   data = f.read()
  201.   raw = list(data)
  202.   pe = pefile.PE(data=data)
  203.   for s in pe.sections:
  204.     entry = {}
  205.     entry['vaddr'] = s.VirtualAddress
  206.     entry['paddr'] = s.PointerToRawData
  207.     entry['vsize'] = s.Misc_VirtualSize
  208.     entry['psize'] = s.SizeOfRawData
  209.     entry['vend'] = entry['vaddr'] + entry['vsize']
  210.     entry['pend'] = entry['paddr'] + entry['psize']
  211.     sections += [entry]
  212. with open("laby2_1107e.exe", 'rb') as f:
  213.   with open("spells.csv", 'w', encoding="utf-8") as o:
  214.     f.read(0x5f4b90)
  215.     c = 0
  216.     while True:
  217.       c += 1
  218.       print(readSpellData(f, o), c)
  219.       o.flush()
  220.  
  221. print("Done!")
  222.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement