Advertisement
Soneek

BFSAR/BCSAR parser/extractor WIP

Dec 22nd, 2015
240
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.88 KB | None | 0 0
  1. import sys
  2. import string
  3. from util import *
  4.  
  5.  
  6. class strg(object):
  7.     name = ""
  8.     size = None
  9.     offset = None
  10.     def __init__(self, id):
  11.         self.id = id
  12.  
  13. class audio(object):
  14.     name = ""
  15.     fileID = None
  16.     strgID = None
  17.     bankID = None
  18.     def __init__(self, id):
  19.         self.id = id
  20.  
  21. class soundSet(object):
  22.     offset = None
  23.     fileID = None
  24.     strgID = None
  25.     def __init__(self, id):
  26.         self.id = id
  27.        
  28. class sarFile(object):
  29.     fileName = ""
  30.     path = ""
  31.     offset = None
  32.     ext = ".b"
  33.     internal = False
  34.     fileOffset = None
  35.     fileInfoLength = None
  36.     size = None
  37.     bank = None
  38.     def __init__(self, id):
  39.         self.id = id
  40.  
  41. class bwav(object):
  42.    
  43.     def __init__(self, id):
  44.         self.id = id
  45.  
  46. class warc(object):
  47.     offset = None
  48.     fileID = None
  49.     sectionCount = None
  50.     wavCount = None
  51.     infoLength = None
  52.     wavs = []
  53.     name = ""
  54.     folder = ""
  55.     def __init__(self, id):
  56.         self.id = id
  57.  
  58. class bank(object):
  59.     offset = None
  60.     fileID = None
  61.     wavs = []
  62.     seqs = []
  63.     name = ""
  64.     folder = ""
  65.     def __init__(self, id):
  66.         self.id = id
  67.  
  68.        
  69. readu16 = readu16be
  70. readu32 = readu32be
  71. sar = open(sys.argv[1], 'rb')
  72. sar.seek(1)
  73. assert sar.read(3) == "SAR"
  74. byteOrder = readu16be(sar)
  75. print hex(byteOrder)
  76. if byteOrder == 0xfeff:
  77.     readu16 = readu16be
  78.     readu32 = readu32be
  79.     endian = ">"
  80. #   print "big endian"
  81. elif byteOrder == 0xfffe:
  82.     readu16 = readu16le
  83.     readu32 = readu32le
  84.     endian = "<"
  85. #   print "little endian"
  86. else:
  87.     print "not found"
  88. #print endian  
  89. sar.seek(0x10)
  90. sectionCount = readu16(sar)
  91. sar.seek(2, 1)
  92. #print sectionCount
  93. #print sys.argv[1] + " opened"
  94. for s in range(0, sectionCount):
  95.     ID = readu16(sar)
  96. #   print hex(ID)
  97.     sar.seek(2, 1)
  98.     if ID == 0x2000:
  99.         strgOffset = readu32(sar)
  100.         strgSize = readu32(sar)
  101.     elif ID == 0x2001:
  102.         infoOffset = readu32(sar)
  103.         infoSize = readu32(sar)
  104.     elif ID == 0x2002:
  105.         fileOffset = readu32(sar)
  106.         fileSize = readu32(sar)
  107.        
  108. # Reading STRG section
  109. sar.seek(strgOffset)
  110. assert sar.read(4) == "STRG"
  111. assert readu32(sar) == strgSize
  112.  
  113. for s in range(0, 2):
  114.     ID = readu16(sar)
  115. #   print hex(ID)
  116.     sar.seek(2, 1)
  117.     if ID == 0x2400:
  118.         strgTableOffset = readu32(sar) + strgOffset + 8
  119.     elif ID == 0x2401:
  120.         strgOtherOffset = readu32(sar) + strgOffset + 8
  121.  
  122. sar.seek(strgTableOffset)
  123. strgCount = readu32(sar)
  124. names = []
  125. for i in range(strgCount):
  126.     names.append(strg(i))
  127.     ID = readu16(sar)
  128.     sar.seek(2, 1)
  129.     if ID ==  0x1f01:
  130.         names[i].offset = readu32(sar) + strgTableOffset
  131.         names[i].size = readu32(sar)
  132.         tempPos = sar.tell()
  133.         sar.seek(names[i].offset)
  134.         names[i].name = sar.read(names[i].size-1)
  135. #       print names[i].name
  136.         sar.seek(tempPos)
  137.     else:   # string may be null
  138.         pass
  139.  
  140.        
  141. # Reading INFO section
  142. sar.seek(infoOffset)
  143. assert sar.read(4) == "INFO"
  144. assert readu32(sar) == infoSize
  145. for i in range(8):
  146.     ID = readu16(sar)
  147. #   print hex(ID)
  148.     sar.seek(2, 1)
  149.     if ID == 0x2100:
  150.         audioTableOffset = readu32(sar) + infoOffset + 8
  151.     elif ID == 0x2101:
  152.         bankTableOffset = readu32(sar) + infoOffset + 8
  153.     elif ID == 0x2102:
  154.         playerTableOffset = readu32(sar) + infoOffset + 8
  155.     elif ID == 0x2103:
  156.         warcTableOffset = readu32(sar) + infoOffset + 8
  157.     elif ID == 0x2104:
  158.         setTableOffset = readu32(sar) + infoOffset + 8
  159.     elif ID == 0x2105:
  160.         groupTableOffset = readu32(sar) + infoOffset + 8
  161.     elif ID == 0x2106:
  162.         fileTableOffset = readu32(sar) + infoOffset + 8
  163.     elif ID == 0x220B:
  164.         fileTableEnd = readu32(sar) + infoOffset + 8
  165.     else:
  166.         print "Unknown table pointer"
  167.         sar.close()
  168.         sys.exit()
  169.  
  170. # process file table
  171. sar.seek(fileTableOffset)
  172. fileCount = readu32(sar)
  173. files = []
  174. for i in range(fileCount):
  175.     sar.seek(fileTableOffset + 4 + i * 8)
  176.     files.append(sarFile(i))
  177.     ID = readu16(sar)
  178. #   print hex(ID)
  179.     sar.seek(2, 1)
  180.     if ID == 0x220a:
  181. #       print "exists"
  182.         files[i].offset = readu32(sar)
  183.     else:
  184.         print "File doesn't exist"
  185.         sar.seek(4, 1)
  186.     sar.seek(fileTableOffset + files[i].offset)
  187.     ID = readu16(sar)
  188. #   print hex(ID)
  189.     sar.seek(10, 1)
  190.     if ID == 0x220c:
  191.         files[i].internal = True
  192.         ID = readu16(sar)
  193.         sar.seek(2, 1)
  194.         if ID != 0xffff:
  195.             offset = readu32(sar)
  196.             if offset != 0xffffffff:
  197.                 files[i].fileOffset = offset + fileOffset + 8
  198.                 files[i].size = readu32(sar)
  199.                 sar.seek(files[i].fileOffset)
  200.                 files[i].ext += string.lower(sar.read(4))
  201. #               print files[i].ext             
  202.     elif ID == 0x220d:
  203.         files[i].path = getString(sar)
  204. #       print files[i].path
  205.        
  206. # process wave archive table
  207. warcs = []
  208. sar.seek(warcTableOffset)
  209. warcCount = readu32(sar)
  210. for i in range(warcCount):
  211.     warcs.append(warc(i))
  212.     sar.seek(warcTableOffset + 4 + i * 8)
  213.     ID = readu16(sar)
  214. #   print hex(ID)
  215.     sar.seek(2, 1)
  216.     if ID == 0x2207:
  217.         warcs[i].offset = readu32(sar)
  218.         sar.seek(warcTableOffset + warcs[i].offset)
  219. #       print hex(sar.tell())
  220.         warcs[i].fileID = readu32(sar)
  221.  
  222. #looping through warcs again to see which ones have a name
  223. for i in range(warcCount):
  224.     fileID = warcs[i].fileID
  225.     if i < warcCount - 1:
  226.         warcs[i].infoLength = warcs[i+1].offset - warcs[i].offset
  227.     else:
  228.         warcs[i].infoLength = groupTableOffset - warcTableOffset - warcs[i].offset
  229.     if warcs[i].infoLength > 0xc:
  230.         sar.seek(warcTableOffset + warcs[i].offset + 0xc)
  231.         strgID = readu32(sar)
  232.         warcs[i].name = names[strgID].name
  233.     else:
  234.         warcs[i].name = "WARC_%s" % hex(i)
  235.     files[fileID].fileName = warcs[i].name + files[fileID].ext
  236.     print files[fileID].fileName
  237.     # now to process wave archive
  238.     if files[fileID].internal and files[fileID].fileOffset != None:
  239.         sar.seek(files[fileID].fileOffset+1)
  240. #       print hex(sar.tell())
  241. #       print sar.read(4)
  242.         assert sar.read(3) == "WAR"
  243.         sar.seek(files[fileID].fileOffset)
  244.         """
  245.         war = open(files[fileID].fileName, "wb")
  246.         war.write(sar.read(files[fileID].size))
  247.         war.close()
  248.         """
  249.         # to be finished
  250.            
  251. # process bank table
  252. banks = []
  253. sar.seek(bankTableOffset)
  254. bankCount = readu32(sar)
  255. print bankCount
  256. for i in range(bankCount):
  257.     banks.append(bank(i))
  258.     sar.seek(bankTableOffset + 4 + i * 8)
  259.     ID = readu16(sar)
  260. #   print hex(ID)
  261.     sar.seek(2, 1)
  262.     if ID == 0x2206:
  263.         banks[i].offset = readu32(sar)
  264.         sar.seek(bankTableOffset + banks[i].offset)
  265.         fileID = banks[i].fileID = readu32(sar)
  266.         sar.seek(0xc,1)
  267.         strgID = banks[i].strgID = readu32(sar)
  268.         banks[i].name = names[strgID].name
  269.         # now to process bank
  270.         if files[fileID].internal and files[fileID].fileOffset != None:
  271.             sar.seek(files[fileID].fileOffset+1)
  272. #           print hex(sar.tell())
  273. #           print sar.read(4)
  274.             assert sar.read(3) == "BNK"
  275.             # to be finished
  276.  
  277. # process audio table
  278. sounds = []
  279. sar.seek(audioTableOffset)
  280. audioCount = readu32(sar)
  281. print audioCount
  282. for i in range(audioCount):
  283.     sounds.append(audio(i))
  284.     sar.seek(audioTableOffset + 4 + i * 8)
  285.     ID = readu16(sar)
  286. #   print hex(ID)
  287.     sar.seek(2, 1)
  288.     if ID == 0x2200:
  289.         sounds[i].offset = readu32(sar)
  290.         sar.seek(audioTableOffset + sounds[i].offset)
  291.         fileID = sounds[i].fileID = readu32(sar)
  292.         sar.seek(8,1)
  293.         typeID = readu16(sar)
  294.         sar.seek(10,1)
  295.         strgID = sounds[i].strgID = readu32(sar)
  296.         sounds[i].name = names[strgID].name
  297.         files[fileID].fileName = sounds[i].name + files[fileID].ext
  298.         if files[fileID].internal:
  299.             pass
  300. #           print files[fileID].fileName
  301.         if typeID == 0x2201:    # External stream
  302.             pass
  303.         elif typeID == 0x2202# Wave sound
  304.             pass
  305. #           print files[fileID].fileName
  306.             sar.seek(files[fileID].fileOffset+1)
  307.             assert sar.read(3) == "WSD"
  308.             sar.seek(files[fileID].fileOffset)
  309.             """
  310.             wsd = open(files[fileID].fileName, "wb")
  311.             wsd.write(sar.read(files[fileID].size))
  312.             wsd.close()
  313.             """
  314.         elif typeID == 0x2203# Sequence
  315.             sar.seek(0x40,1)
  316.             if fileID == 207:
  317.                 print hex(sar.tell())
  318.             bankID = sounds[i].bankID = readByte(sar)
  319. #           print hex(bankID)
  320. #           banks[sounds[i].bankID].seqs.append(1)
  321.             sar.seek(files[fileID].fileOffset+1)
  322.             assert sar.read(3) == "SEQ"
  323.  
  324. print hex(bankCount)
  325.  
  326. #for i in range(bankCount):
  327. #   print banks[i].name
  328. #   print "\t" + str(len(banks[i].seqs))
  329. #   for j in range(len(banks[i].seqs)):
  330. #       print "\t" + files[banks[i].seqs[j]].fileName
  331.  
  332.        
  333. sar.close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement