#!/usr/bin/env python

import sys,zlib,StringIO,os,os.path

def s2d(s):
       """Interprets a 4-character string as a little-endien numerical DWORD value"""
       assert(len(s)==4)
       v = [ord(c) for c in s]
       d = v[0] + (v[1]<<8) + (v[2]<<16) + (v[3]<<24)
       return d

filename = sys.argv[1]
arcfile = open(filename,'rb')

signature = s2d(arcfile.read(4))
assert(signature == 0x2)

numfiles = s2d(arcfile.read(4))
indexsizeuncompressed = s2d(arcfile.read(4))
indexsizecompressed = s2d(arcfile.read(4))
key = s2d(arcfile.read(4))
assert(key == 0x64)

gameid = arcfile.read(256)
assert(gameid.strip('\x00')=="jingaimakyou")

indexcompressed = arcfile.read(indexsizecompressed)
indexstr = zlib.decompress(indexcompressed)
assert(len(indexstr)==indexsizeuncompressed)
indexfile = StringIO.StringIO(indexstr)

indexend = 276 + indexsizecompressed

while(indexfile.tell() < indexsizeuncompressed):
       filenamelen = s2d(indexfile.read(4))
       filename = indexfile.read(filenamelen)
       offset = s2d(indexfile.read(4))
       size = s2d(indexfile.read(4))
       wtf = s2d(indexfile.read(4)) #Don't know what this field is - normally the same as previous
       assert(wtf==size)
       cflag = s2d(indexfile.read(4)) #Compression flag
       assert(cflag in (1,0))
       csize = s2d(indexfile.read(4)) #Compressed size
       if(cflag==0):
               assert(csize==0)

       arcfile.seek(indexend + offset)
       if(cflag):
               cdata = arcfile.read(csize)
               data = zlib.decompress(cdata)
               assert(len(data) == size)
       else:
               data = arcfile.read(size)

       osfilename = os.path.join(*filename.split('\\')) #OS-independent filename - archive (unsurprisingly) assumes windows
       dir = os.path.dirname(osfilename)
       if(dir and not os.path.exists(dir)): os.makedirs(dir) #Create the directory if necessary
       outfile = open(osfilename,'wb')
       outfile.write(data)
       outfile.close()

indexfile.close()
arcfile.close()