首  页   最新日志    火人论坛        火人作品    编程园地    网络日志    网友作品     留言本本     关于火人
用户登陆
用户:
密码:
 

站点日历
73 2017 - 11 48
   1234
567891011
12131415161718
19202122232425
2627282930




日志搜索

 标题   内容

 
 
传奇源码分析-服务器端(LoginSvr服务器分析) SpriteEngine4例程大全(一)
雨天 冒险岛资源浏览器Ver2.0
   [分类:火人作品][发表日期:2007-3-17] [发表:火人[查看:261916]

按此在新窗口打开图片

    这次回老家过年时间较长,没什么好东西带给大家,闲暇时将冒险岛资源浏览器升级了,增加或改进了如下功能:
1、可导出图片和歌曲,存储为PNG和MP3格式
2、解除了资源提取数量<600的限制
3、可输出相关游戏数据,并以树的形式显示,也可输出为HTM文件(如下图)
按此在新窗口打开图片    按此在新窗口打开图片
点击下载冒险岛资源浏览器Ver2.0
点击下载d3dx9_28.rar

声明:本软件仅用于玩家娱乐或编程交流,软件中所用技术均来自网络,若无意中侵犯到您的权利,敬请来电联系。
读取0.63以后新版本的浏览器请到此下载:http://www.huosoft.com/blogview.asp?logID=117





[本日志由 火人 于 2009-03-16 03:15 AM 编辑]

[1] [2] [3] [4] [5] 

引用这个评论 occump 于 2017-01-22 12:57 AM 发表评论: 
[url=http://zsearchdom3.com]zsearchdom3.com[/url] [url]http://zsearchdom4.com[/url] <a href="http://zsearchdom1.com">zsearchdom1.com</a> http://zsearchdom5.com [url="http://zsearchdom2.com"]zsearchdom2.com[/url] 

引用这个评论 wzj5 于 2008-06-28 08:04 PM 发表评论: 
无法打开  新版本的啊

引用这个评论 h93910 于 2008-05-27 08:13 PM 发表评论: 
冒险岛更新了,有些图已经不能解出来了,我有个建议,可否将此软件更新一下

引用这个评论 布丁 于 2008-05-06 06:22 AM 发表评论: 
请问为什么提取出来的音乐音质都很差? 只有 22kHz 80Kbps, 而官方网站上有下载的, 都有44kHz 192Kbps, 我试了根据提取出的HTML里的偏移数据自己手动去提取, 发现也只有22 kHz, 难道冒险岛这个游戏里提供的是如此低音质的背景音乐?

引用这个评论 Fanxy 于 2008-04-24 06:11 PM 发表评论: 
那段导出的代码以前能用,现在061只能提取开头的一点图片,有什么解决办法不

引用这个评论 o8u8o 于 2008-04-15 09:56 AM 发表评论: 
如果批量导出真的难的话,
指定导出也可以 只要能一次能吧一个【序号】内的文件全导出来就可以了,并没有蓝条
可以自己指定 导出的序号

引用这个评论 o8u8o 于 2008-04-15 09:43 AM 发表评论: 
为什么用你的脚本 只能提取很少的开头一部分
为什么不是全部?

引用这个评论 狂人 于 2008-04-13 01:40 PM 发表评论: 
我装了DX9以后这个工具就不好使了?怎么回事?

引用这个评论 hotpk 于 2008-04-07 11:01 PM 发表评论: 
为什么不支持导入呀~~~

引用这个评论 冒险仙剑迷 于 2008-04-04 07:52 PM 发表评论: 
弓虽,不过你的源代码在哪儿公开啊?而且公开后我看不看得懂海狮的问题 ……

引用这个评论  于 2008-01-25 04:34 PM 发表评论: 
为什么BasicEFF里的图片不能导出呢?

引用这个评论 ypwhs 于 2008-01-20 08:32 PM 发表评论: 
想要批量导出的而且没有蓝边的话,只需要用很久以前的一个脚本就行了  

import struct
import zlib
import sys
import os

# ===========================================
# ============= Tree Flattening =============
# ===========================================

def flattenName(parent, child):
  if(parent == ""): return child
  else: return "%s.%s" % (parent, child)

def flattenRecurse(vals, name = ""):
  global flattenReturn
  if(type(vals) == type([])):
    if(type(vals[0]) == type("")):
      if(type(vals[1]) != type([])):
        result = [flattenName(name, vals[0]), vals[1]]
        flattenReturn.append(result)
      else:
        for val in vals[1:]:
          flattenRecurse(val, flattenName(name, vals[0]))
    else:
      for val in vals:
        flattenRecurse(val, name)

def flatten(vals):
  global flattenReturn
  flattenReturn = []
  flattenRecurse(vals)
  return flattenReturn

# ===========================================
# ============== Final Output ===============
# ===========================================

# findImage should work for image*'s, but the image*'s
#  aren't always valid, or possibly point to a parent
#  class's image...

#def findImage(name, vals):
#  name = name.replace("/", ".")
#  name = "%s.image" % name
#  for val in vals:
#    if(val[0] == name): return val[1]
#
#  name = "%s*" % name
#  for val in vals:
#    if(val[0] == name): return findImage(val[1], vals)
#
#  print "Could not find image %s" % name
#  sys.exit(-1)

def endMatches(str, values):
  for s in values:
    if(str[-len(s):] == s): return 1
  return 0

def textOut(vals):
  for val in vals:
    print "%s: %s" % (val[0], val[1])
  # Code used for testing findImage... which doesn't work (see above note)
  #for val in vals:
  #  if(endMatches(val[0], ["image*"])):
  #    print "Searching for %s: %s" % (val[0], val[1])
  #    print "%s: %s)" % (val[0][:-1], findImage(val[1], vals), val[1])
  #  else:
  #    print "%s: %s" % (val[0], val[1])

def htmlOut(vals):
  print "<table>"
  for val in vals:
    if(endMatches(val[0], ["image"])):
      print "<tr><td>%s</td><td><img src='%s'></td></tr>" % (val[0], val[1])
    elif(endMatches(val[0], ["mp3"])):
      print "<tr><td>%s</td><td><a href='%s'>mp3</a></td></tr>" % (val[0], val[1])
    else:
      print "<tr><td>%s</td><td>%s</td></tr>" % (val[0], val[1])
  print "</table>"

def safe_mkdir(dirName):
  try:
    os.mkdir(dirName)
  except OSError, (errno, strerror):
    if(errno != 17):
      print "%d: %s" % (errno, strerror)
      sys.exit(-1)

# ===========================================
# ============ PNG/Image Routines ===========
# ===========================================

def pack_chunk(tag,data):
  to_check = tag + data
  return struct.pack("!I",len(data)) +          to_check +          struct.pack("!I",zlib.crc32(to_check))

def dumpToPNG(width, height, data):
  raw_data = ""
  for y in range(height):
    raw_data += chr(0)
    raw_data += data[y*width*4:(y+1)*width*4]

  return struct.pack("8B", 137, 80, 78, 71, 13, 10, 26, 10) +          pack_chunk('IHDR',
           struct.pack("!IIBBBBB",width,height,8,6,0,0,0)) +          pack_chunk('IDAT', zlib.compress(raw_data,9)) +          pack_chunk('IEND', '')

def image16to32(width, height, data):
  datalen = len(data)
  buf = ""
  for i in range(width*height):
    # Not all images decompress correectly. This makes up for it.
    if(i > datalen/2 - 1):
      p = [0,0]
    else:
      p = struct.unpack("BB", data[i*2:i*2+2])

    a = p[1] / 16 ; a = a*16 + a
    r = p[1] % 16 ; r = r*16 + r
    g = p[0] / 16 ; g = g*16 + g
    b = p[0] % 16 ; b = b*16 + b

    if(a >  255): a = 255
    if(r >  255): r = 255
    if(g >  255): g = 255
    if(b >  255): b = 255

    buf += struct.pack("BBBB", r, g, b, a)
  return buf

# ===========================================
# =========== Abort/Debug Routines ==========
# ===========================================

def printItem(name, value):
  print "%-30s: %s" % (name, value)

def check(flag, val, f, msg="Default Error"):
  if(flag != val):
    item  = "Unknown: %s" % repr(flag) ; value = "Expecting: %s" % repr(val)
    printItem(item, value)
    printItem("Error", msg)
    printItem("FileLocation", repr(f.tell()))
    sys.exit(-1)

def checkA(flag, vals, f, msg="Default Error"):
  if(not flag in vals):
    item  = "Unknown: %s" % repr(flag) ; value = "Expecting: %s" % repr(vals)
    printItem(item, value)
    printItem("Error", msg)
    printItem("FileLocation", repr(f.tell()))
    sys.exit(-1)

# ===========================================
# ============ Basic File Reading ===========
# ===========================================

def rU8 (f): return struct.unpack('B', f.read(1))[0]
def rS8 (f): return struct.unpack('b', f.read(1))[0]
def rU16(f): return struct.unpack('H', f.read(2))[0]
def rU32(f): return struct.unpack('I', f.read(4))[0]
def rS32(f): return struct.unpack('i', f.read(4))[0]
def rU64(f): return struct.unpack('Q', f.read(8))[0]
def rF32(f): return struct.unpack('f', f.read(4))[0]
def rF64(f): return struct.unpack('d', f.read(8))[0]

def rPackNum(f):
  size = rS8(f)
  if(size == -128): size = rS32(f)
  return size

# ===========================================
# ============ String Decryption ============
# ===========================================

def hexStr(s):
  str = ''
  for c in s:
    str += "\\x%02x" % ord(c)
  return str

def xor  (a, p): return  ((a & ~p) ^ (~a & p)) & 0xff
def xor16(a, p): return  ((a & ~p) ^ (~a & p)) & 0xffff

def transStr(str):
  s = ''
  p = 0xAA
  for cc in str:
    a = ord(cc)
    s += struct.pack("B", xor(a,p) )
    p += 1
  return s

def transStr16(str):
  s = ''
  p = 0xAAAA
  for i in range(len(str)/2):
    a = struct.unpack("h", str[i*2:i*2+2])
    s += struct.pack("h", xor16(a,p) )
    p += 1
  return s

# ===========================================
# ========= External File Extraction ========
# ============= (MP3s and PNGs) =============
# ===========================================

def dumpImage(f, imageName):
  global dumpDir
  global dumpImages

  width  = rPackNum(f)
  height = rPackNum(f)
  val   = rPackNum(f)    ; checkA(val, [0, 1, 2, 10, 513], f)
  val2  = rU8(f)         ; checkA(val2, [0, 2, 4], f)
  nulls = f.read(4)      ; check(nulls, "\x00\x00\x00\x00", f, "Dump Image")
  bufSize = rU32(f) - 1
  flag = rU8(f)          ; check(flag,  0x00, f);

  if(not dumpImages):
    f.seek(bufSize, 1)
  else:
    obj = zlib.decompressobj()
    buf = obj.decompress(f.read(bufSize))
    if(width*height*2 != len(buf)): print "Bad image: %s" % imageName
    g = open(dumpDir + imageName, "wb")
    g.write(dumpToPNG(width, height, image16to32(width, height, buf)))
    g.close()

def dumpMp3(f, size, endOfBlock):
  startOfMP3 = endOfBlock - size
  remaining = startOfMP3 - f.tell()
  #unknown = f.read(remaining)
  #g = open("%d.mp3" % mp3count, "wb")
  #g.write(f.read(size))
  #g.close()
  #mp3count += 1
  f.seek(endOfBlock)

# ===========================================
# ================= Header ==================
# ===========================================

def extractHeader(f):
  v = {}
  v["FileIdentity"] = f.read(4)
  v["FileSize"]     = rU64(f)
  v["FileStart"]    = rU32(f)
  v["Copyright"]    = f.read(v["FileStart"] - f.tell())
  return v

# ===========================================
# ========== Directory / File Tree ==========
# ===========================================

def extractDirectory(f, baseName, blockOffset):
  global eFiles

  dirs  = []
  entryCount = rPackNum(f)
  for j in range(entryCount):
    filetype = rU8(f)    ; checkA(filetype, [0x02, 0x03, 0x04], f)
    if(filetype in [0x03, 0x04]):
      filename = rUStr(f)
    if(filetype in [0x02]):
      filenameloc  = rU32(f)
      filename = rUStrAt(f, filenameloc, blockOffset)
    filesize = rPackNum(f)
    unknown1 = rPackNum(f)
    unknown2 = rU32(f)

    v = {"Name": baseName + "/" + filename,
         "Size": filesize,
         "Unk1": unknown1,
         "Unk2": unknown2}

    if(filetype in [0x03]):
      dirs.append(v)
    if(filetype in [0x02, 0x04]):
      eFiles.append(v)

  for dir in dirs:
    extractDirectory(f, dir["Name"], blockOffset)

def computeFileOffsets(fileBase):
  global eFiles

  totalOffset = 0
  for file in eFiles:
    file["Offset"] = fileBase + totalOffset
    totalOffset += file["Size"]

def extractDirectories(f, blockOffset):
  global eFiles
  eFiles = []
  extractDirectory(f, "", blockOffset)
  computeFileOffsets(f.tell())
  return eFiles

def extractDirTree(f, blockOffset):
  v = {}
  v["Unknown"] = rU16(f)
  v["Files"]   = extractDirectories(f, blockOffset)
  return v

# ===========================================
# ============= Everything else =============
# ===========================================

def subBlock(f, count, endOfBlock = 0):
  result = []
  if(count == 0): return '-NONE-'
  for i in range(count):
    flag = rU8(f)  ; check(flag, 0x1b, f)
    type = rU32(f)
    val1 = rPackNum(f) ; val2 = 0
    if(f.tell() != endOfBlock):
      val2 = rPackNum(f)
    result.append([val1, val2])
  return result

def rUStr(f): return extract00type(f)
def rUStrAt(f, loc, baseOffset): return extract00typeAt(f, loc, baseOffset)

previousStrings = {}
parsingFileTree = 0
def extract00type(f):
  size = rS8(f)
  if(size == 0):
    return ''
  elif(size < 0):
    if(size == -128): size = rU32(f)
    else:             size = -size
    result = transStr(f.read(size))

    # Keep a list of previous translations
    global previousStrings
    previousStrings[result] = 0

    return result
  elif(size > 0):
    if(size == 127): size = rU32(f)

    global parsingFileTree
    if(parsingFileTree):
      subSize = rS8(f) ; subCount = 1
      if(subSize < 0): subSize = -subSize
      else:            subSize = rU32(f) ; subCount += 4
      subStr  = transStr(f.read(size*2 - subCount))

      for previousString in previousStrings.keys():
        if((len(previousString) == subSize) and 
           (previousString[0:size*2-1] == subStr)):
          return previousString
      print "Can't find String '%s' at %d" % (subStr, f.tell())
      sys.exit(-1)
    else:
      if(size == 1):
        val = rU16(f)
        val = xor16(val, 0x558a)
        if(val < 256):
          return chr(val)
        else:
          f.seek(-2, 1)
      
      result = f.read(size*2)
      
      ##transStr16 does not work in all cases...
      ## plus it needs extra UTF-16 to UTF-8 encoding
      ## handling.  So for now, just return the hexStr
      ## of it.  Maybe someone else can figure it out.
      # results = transStr16(result)
      return hexStr(result)

def extract00typeAt(f, loc, baseOffset):
  pos = f.tell()
  f.seek(loc + baseOffset, 0)
  value = extract00type(f)
  f.seek(pos)
  return value

def extract01type(f, baseOffset):
  loc = rU32(f)
  return extract00typeAt(f, loc, baseOffset)

def extract02type(f):
  return rU16(f)

def extract03type(f):
  return rPackNum(f)

def extract04type(f):
  type = rU8(f) ; checkA(type, [0x00, 0x80], f, "0x04 type")
  if   (type == 0x80): return rF32(f)
  elif (type == 0x00): return 0

def extract05type(f):
  return rF64(f)

def extract08type(f, name, baseOffset):
  return dumpBlock(f, name, baseOffset)

def extract09type(f, name, baseOffset):
  size = rU32(f)
  loc = f.tell()
  endOfBlock = f.tell() + size
  result = dumpBlock(f, name, baseOffset, f.tell() + size)
  if(f.tell() != endOfBlock):
    print "Incomplete Block [%s] at offset %d, size: %d, loc: %d" % (name, loc, size, f.tell())
    f.seek(endOfBlock, 0)
    sys.exit(-1)
  return result

def extract1btype(f, name, baseOffset, endOfBlock):
  flag  = rU16(f)
  flagb = rU16(f)

  locb  = f.tell()
  
  val1 = rPackNum(f) ; val2 = 0
  if(f.tell() != endOfBlock):
    val2 = rPackNum(f)

  if(f.tell() == endOfBlock):
    return [['x', val1], ['y', val2]]

  f.seek(locb, 0)
  val1 = rU8(f)
  if(val1 == 0x00):
    val2 = rU8(f) ; subt = 0
    if(val2 not in [0x00, 0x80] and flag != 0x01):
      nil = rU16(f)  ; check(nil,  0x00, f, "Inner 1b type1")

    if(val2 == 0x80):
      size = rU32(f)
      dumpMp3(f, size, endOfBlock)
      return ["mp3", name]
    else:
      vals = []
      if(not (val1 == 0x00 and val2 == 0x00) or (flag == 0x01)):
        descCount = rPackNum(f)
        for j in range(descCount):
          qname = dumpBlock(f, name, baseOffset)
          val = dumpEntryValue(f, name + "/" + str(qname), baseOffset)
          vals.append([qname, val])

      if(f.tell() == endOfBlock):
        if(vals == []): return '-NONE-'
        else:           return vals
      else:
        imgname = name.replace('/', '.') + ".png"
        dumpImage(f, imgname)
        vals.append(['image', imgname])
        return vals
  else:
    blockval = val1
    return subBlock(f, val1, endOfBlock)

def computeName(image, name):
  name = name[0:name.rfind("/")+1]
  while(image[0:3] == "../"):
    name = name[0:-1]
    name = name[0:name.rfind("/")+1]
    image = image[3:]
  return name + image

def extract73type(f, name, baseOffset, endOfBlock):
  iname = rUStr(f)
  if(iname == "Shape2D#Convex2D"):
    count = rPackNum(f)
    return subBlock(f, count, endOfBlock)
  if(iname == "Shape2D#Vector2D"):
    val1 = rPackNum(f)
    val2 = rPackNum(f)
    return [["x", val1], ["y", val2]]
  if(iname == "Canvas"):
    space = rU16(f)  ; checkA(space, [0, 256], f)
    if(space == 256):
      nil = rU16(f)
      count = rU8(f)
      for i in range(count):
        qname = dumpBlock(f, name, baseOffset)
        val = dumpEntryValue(f, name + "/" + str(qname), baseOffset)
    imgname = name.replace('/', '.') + ".png"
    dumpImage(f, imgname)
    return ['image', imgname]
  if(iname == "UOL"):
    nil = rU8(f)
    image = dumpBlock(f, name, baseOffset)
    cName = computeName(image, name)
    return ['image*', cName]
  if(iname == "Sound_DX8"):
    nil = rU8(f)
    size = rPackNum(f)
    dumpMp3(f, size, endOfBlock)
    return ["mp3", name]
# ---------------------------------------------

def dumpBlock(f, name, baseOffset, endOfBlock = 0):
  global vals
  type = rU8(f)

  if   (type == 0x00): return extract00type(f)
  elif (type == 0x01): return extract01type(f, baseOffset)
  elif (type == 0x1b): return extract1btype(f, name, baseOffset, endOfBlock)
  elif (type == 0x73): return extract73type(f, name, baseOffset, endOfBlock)

def dumpEntryValue(f, name, baseOffset):
  global vals
  type = rU8(f)

  if   (type == 0x00): return "-NIL-"
  elif (type == 0x02): return extract02type(f)
  elif (type == 0x03): return extract03type(f)
  elif (type == 0x04): return extract04type(f)
  elif (type == 0x05): return extract05type(f)
  elif (type == 0x08): return extract08type(f, name, baseOffset)
  elif (type == 0x09): return extract09type(f, name, baseOffset)

def dumpFile(f, sname, baseOffset):
  global vals
  vals = {}

  flag = rU8(f)      ; check(flag, 0x73, f)
  imgName = rUStr(f) ; check(imgName, "Property", f)
  space = rU8(f)     ; check(space, 0x00, f, "File Outer Space")
  space = rU8(f)     ; check(space, 0x00, f, "File Outer Space 2")
  entries = rPackNum(f)
  
  vals = []
  for i in range(entries):
    name  = dumpBlock(f, sname, baseOffset)
    value = dumpEntryValue(f, str(name), baseOffset)
    vals.append([name, value])
  return vals


def dump():
  global dumpImages, dumpHTML
  global dumpDir, dumpDirBase
  f = open("文件名", "rb")

  if(dumpImages or dumpHTML):
    safe_mkdir(dumpDirBase)
    origstdout = sys.stdout

  header = extractHeader(f)
  DirTreeOffset = f.tell()

  global parsingFileTree
  parsingFileTree = 1
  dirTree = extractDirTree(f, DirTreeOffset)
  parsingFileTree = 0

  for i in range(len(dirTree["Files"])):
    file = dirTree["Files"][i]
    f.seek(file["Offset"], 0)

    if(dumpImages or dumpHTML):
      dumpDir = dumpDirBase + file["Name"].replace("/", ".") + "/"
      safe_mkdir(dumpDir)

    print "%4d: %s, %d, %d" % (i, repr(file["Name"])[1:-1], file["Size"], file["Offset"])

    vals = dumpFile(f, file["Name"], file["Offset"])
    vals = flatten(vals)
    if(dumpHTML):
      g = open(dumpDir + "index.html", "w")
      sys.stdout = g

      htmlOut(vals)

      g.close
      sys.stdout = origstdout
    else:
      textOut(vals)

dumpImages = 1
dumpHTML = 1

dumpDirBase = "dump/"
dumpDir     = dumpDirBase

dump()

把这段代码复制到记事本中,把代码中"文件名"(Ctrl+f 搜索)改成你要提取的文件(列如:map.wz),然后把扩展名改为.py
然后安装python-2.4.2.msi(网上去搜)以支持代码运行,把你刚才保存的文件复制到冒险岛的目录中,双击打开此文件,系统自动提取,你只需要耐心的等,提取出来的文件保存在冒险岛的目录中多出来的一个文件夹中!

引用这个评论 tangke300 于 2007-12-23 11:31 AM 发表评论: 
想要批量导出的而且没有蓝边的话,只需要用很久以前的一个脚本就行了

import struct
import zlib
import sys
import os

# ===========================================
# ============= Tree Flattening =============
# ===========================================

def flattenName(parent, child):
  if(parent == ""): return child
  else: return "%s.%s" % (parent, child)

def flattenRecurse(vals, name = ""):
  global flattenReturn
  if(type(vals) == type([])):
    if(type(vals[0]) == type("")):
      if(type(vals[1]) != type([])):
        result = [flattenName(name, vals[0]), vals[1]]
        flattenReturn.append(result)
      else:
        for val in vals[1:]:
          flattenRecurse(val, flattenName(name, vals[0]))
    else:
      for val in vals:
        flattenRecurse(val, name)

def flatten(vals):
  global flattenReturn
  flattenReturn = []
  flattenRecurse(vals)
  return flattenReturn

# ===========================================
# ============== Final Output ===============
# ===========================================

# findImage should work for image*'s, but the image*'s
#  aren't always valid, or possibly point to a parent
#  class's image...

#def findImage(name, vals):
#  name = name.replace("/", ".")
#  name = "%s.image" % name
#  for val in vals:
#    if(val[0] == name): return val[1]
#
#  name = "%s*" % name
#  for val in vals:
#    if(val[0] == name): return findImage(val[1], vals)
#
#  print "Could not find image %s" % name
#  sys.exit(-1)

def endMatches(str, values):
  for s in values:
    if(str[-len(s):] == s): return 1
  return 0

def textOut(vals):
  for val in vals:
    print "%s: %s" % (val[0], val[1])
  # Code used for testing findImage... which doesn't work (see above note)
  #for val in vals:
  #  if(endMatches(val[0], ["image*"])):
  #    print "Searching for %s: %s" % (val[0], val[1])
  #    print "%s: %s)" % (val[0][:-1], findImage(val[1], vals), val[1])
  #  else:
  #    print "%s: %s" % (val[0], val[1])

def htmlOut(vals):
  print "<table>"
  for val in vals:
    if(endMatches(val[0], ["image"])):
      print "<tr><td>%s</td><td><img src='%s'></td></tr>" % (val[0], val[1])
    elif(endMatches(val[0], ["mp3"])):
      print "<tr><td>%s</td><td><a href='%s'>mp3</a></td></tr>" % (val[0], val[1])
    else:
      print "<tr><td>%s</td><td>%s</td></tr>" % (val[0], val[1])
  print "</table>"

def safe_mkdir(dirName):
  try:
    os.mkdir(dirName)
  except OSError, (errno, strerror):
    if(errno != 17):
      print "%d: %s" % (errno, strerror)
      sys.exit(-1)

# ===========================================
# ============ PNG/Image Routines ===========
# ===========================================

def pack_chunk(tag,data):
  to_check = tag + data
  return struct.pack("!I",len(data)) +          to_check +          struct.pack("!I",zlib.crc32(to_check))

def dumpToPNG(width, height, data):
  raw_data = ""
  for y in range(height):
    raw_data += chr(0)
    raw_data += data[y*width*4:(y+1)*width*4]

  return struct.pack("8B", 137, 80, 78, 71, 13, 10, 26, 10) +          pack_chunk('IHDR',
           struct.pack("!IIBBBBB",width,height,8,6,0,0,0)) +          pack_chunk('IDAT', zlib.compress(raw_data,9)) +          pack_chunk('IEND', '')

def image16to32(width, height, data):
  datalen = len(data)
  buf = ""
  for i in range(width*height):
    # Not all images decompress correectly. This makes up for it.
    if(i > datalen/2 - 1):
      p = [0,0]
    else:
      p = struct.unpack("BB", data[i*2:i*2+2])

    a = p[1] / 16 ; a = a*16 + a
    r = p[1] % 16 ; r = r*16 + r
    g = p[0] / 16 ; g = g*16 + g
    b = p[0] % 16 ; b = b*16 + b

    if(a >  255): a = 255
    if(r >  255): r = 255
    if(g >  255): g = 255
    if(b >  255): b = 255

    buf += struct.pack("BBBB", r, g, b, a)
  return buf

# ===========================================
# =========== Abort/Debug Routines ==========
# ===========================================

def printItem(name, value):
  print "%-30s: %s" % (name, value)

def check(flag, val, f, msg="Default Error"):
  if(flag != val):
    item  = "Unknown: %s" % repr(flag) ; value = "Expecting: %s" % repr(val)
    printItem(item, value)
    printItem("Error", msg)
    printItem("FileLocation", repr(f.tell()))
    sys.exit(-1)

def checkA(flag, vals, f, msg="Default Error"):
  if(not flag in vals):
    item  = "Unknown: %s" % repr(flag) ; value = "Expecting: %s" % repr(vals)
    printItem(item, value)
    printItem("Error", msg)
    printItem("FileLocation", repr(f.tell()))
    sys.exit(-1)

# ===========================================
# ============ Basic File Reading ===========
# ===========================================

def rU8 (f): return struct.unpack('B', f.read(1))[0]
def rS8 (f): return struct.unpack('b', f.read(1))[0]
def rU16(f): return struct.unpack('H', f.read(2))[0]
def rU32(f): return struct.unpack('I', f.read(4))[0]
def rS32(f): return struct.unpack('i', f.read(4))[0]
def rU64(f): return struct.unpack('Q', f.read(8))[0]
def rF32(f): return struct.unpack('f', f.read(4))[0]
def rF64(f): return struct.unpack('d', f.read(8))[0]

def rPackNum(f):
  size = rS8(f)
  if(size == -128): size = rS32(f)
  return size

# ===========================================
# ============ String Decryption ============
# ===========================================

def hexStr(s):
  str = ''
  for c in s:
    str += "\\x%02x" % ord(c)
  return str

def xor  (a, p): return  ((a & ~p) ^ (~a & p)) & 0xff
def xor16(a, p): return  ((a & ~p) ^ (~a & p)) & 0xffff

def transStr(str):
  s = ''
  p = 0xAA
  for cc in str:
    a = ord(cc)
    s += struct.pack("B", xor(a,p) )
    p += 1
  return s

def transStr16(str):
  s = ''
  p = 0xAAAA
  for i in range(len(str)/2):
    a = struct.unpack("h", str[i*2:i*2+2])
    s += struct.pack("h", xor16(a,p) )
    p += 1
  return s

# ===========================================
# ========= External File Extraction ========
# ============= (MP3s and PNGs) =============
# ===========================================

def dumpImage(f, imageName):
  global dumpDir
  global dumpImages

  width  = rPackNum(f)
  height = rPackNum(f)
  val   = rPackNum(f)    ; checkA(val, [0, 1, 2, 10, 513], f)
  val2  = rU8(f)         ; checkA(val2, [0, 2, 4], f)
  nulls = f.read(4)      ; check(nulls, "\x00\x00\x00\x00", f, "Dump Image")
  bufSize = rU32(f) - 1
  flag = rU8(f)          ; check(flag,  0x00, f);

  if(not dumpImages):
    f.seek(bufSize, 1)
  else:
    obj = zlib.decompressobj()
    buf = obj.decompress(f.read(bufSize))
    if(width*height*2 != len(buf)): print "Bad image: %s" % imageName
    g = open(dumpDir + imageName, "wb")
    g.write(dumpToPNG(width, height, image16to32(width, height, buf)))
    g.close()

def dumpMp3(f, size, endOfBlock):
  startOfMP3 = endOfBlock - size
  remaining = startOfMP3 - f.tell()
  #unknown = f.read(remaining)
  #g = open("%d.mp3" % mp3count, "wb")
  #g.write(f.read(size))
  #g.close()
  #mp3count += 1
  f.seek(endOfBlock)

# ===========================================
# ================= Header ==================
# ===========================================

def extractHeader(f):
  v = {}
  v["FileIdentity"] = f.read(4)
  v["FileSize"]     = rU64(f)
  v["FileStart"]    = rU32(f)
  v["Copyright"]    = f.read(v["FileStart"] - f.tell())
  return v

# ===========================================
# ========== Directory / File Tree ==========
# ===========================================

def extractDirectory(f, baseName, blockOffset):
  global eFiles

  dirs  = []
  entryCount = rPackNum(f)
  for j in range(entryCount):
    filetype = rU8(f)    ; checkA(filetype, [0x02, 0x03, 0x04], f)
    if(filetype in [0x03, 0x04]):
      filename = rUStr(f)
    if(filetype in [0x02]):
      filenameloc  = rU32(f)
      filename = rUStrAt(f, filenameloc, blockOffset)
    filesize = rPackNum(f)
    unknown1 = rPackNum(f)
    unknown2 = rU32(f)

    v = {"Name": baseName + "/" + filename,
         "Size": filesize,
         "Unk1": unknown1,
         "Unk2": unknown2}

    if(filetype in [0x03]):
      dirs.append(v)
    if(filetype in [0x02, 0x04]):
      eFiles.append(v)

  for dir in dirs:
    extractDirectory(f, dir["Name"], blockOffset)

def computeFileOffsets(fileBase):
  global eFiles

  totalOffset = 0
  for file in eFiles:
    file["Offset"] = fileBase + totalOffset
    totalOffset += file["Size"]

def extractDirectories(f, blockOffset):
  global eFiles
  eFiles = []
  extractDirectory(f, "", blockOffset)
  computeFileOffsets(f.tell())
  return eFiles

def extractDirTree(f, blockOffset):
  v = {}
  v["Unknown"] = rU16(f)
  v["Files"]   = extractDirectories(f, blockOffset)
  return v

# ===========================================
# ============= Everything else =============
# ===========================================

def subBlock(f, count, endOfBlock = 0):
  result = []
  if(count == 0): return '-NONE-'
  for i in range(count):
    flag = rU8(f)  ; check(flag, 0x1b, f)
    type = rU32(f)
    val1 = rPackNum(f) ; val2 = 0
    if(f.tell() != endOfBlock):
      val2 = rPackNum(f)
    result.append([val1, val2])
  return result

def rUStr(f): return extract00type(f)
def rUStrAt(f, loc, baseOffset): return extract00typeAt(f, loc, baseOffset)

previousStrings = {}
parsingFileTree = 0
def extract00type(f):
  size = rS8(f)
  if(size == 0):
    return ''
  elif(size < 0):
    if(size == -128): size = rU32(f)
    else:             size = -size
    result = transStr(f.read(size))

    # Keep a list of previous translations
    global previousStrings
    previousStrings[result] = 0

    return result
  elif(size > 0):
    if(size == 127): size = rU32(f)

    global parsingFileTree
    if(parsingFileTree):
      subSize = rS8(f) ; subCount = 1
      if(subSize < 0): subSize = -subSize
      else:            subSize = rU32(f) ; subCount += 4
      subStr  = transStr(f.read(size*2 - subCount))

      for previousString in previousStrings.keys():
        if((len(previousString) == subSize) and 
           (previousString[0:size*2-1] == subStr)):
          return previousString
      print "Can't find String '%s' at %d" % (subStr, f.tell())
      sys.exit(-1)
    else:
      if(size == 1):
        val = rU16(f)
        val = xor16(val, 0x558a)
        if(val < 256):
          return chr(val)
        else:
          f.seek(-2, 1)
      
      result = f.read(size*2)
      
      ##transStr16 does not work in all cases...
      ## plus it needs extra UTF-16 to UTF-8 encoding
      ## handling.  So for now, just return the hexStr
      ## of it.  Maybe someone else can figure it out.
      # results = transStr16(result)
      return hexStr(result)

def extract00typeAt(f, loc, baseOffset):
  pos = f.tell()
  f.seek(loc + baseOffset, 0)
  value = extract00type(f)
  f.seek(pos)
  return value

def extract01type(f, baseOffset):
  loc = rU32(f)
  return extract00typeAt(f, loc, baseOffset)

def extract02type(f):
  return rU16(f)

def extract03type(f):
  return rPackNum(f)

def extract04type(f):
  type = rU8(f) ; checkA(type, [0x00, 0x80], f, "0x04 type")
  if   (type == 0x80): return rF32(f)
  elif (type == 0x00): return 0

def extract05type(f):
  return rF64(f)

def extract08type(f, name, baseOffset):
  return dumpBlock(f, name, baseOffset)

def extract09type(f, name, baseOffset):
  size = rU32(f)
  loc = f.tell()
  endOfBlock = f.tell() + size
  result = dumpBlock(f, name, baseOffset, f.tell() + size)
  if(f.tell() != endOfBlock):
    print "Incomplete Block [%s] at offset %d, size: %d, loc: %d" % (name, loc, size, f.tell())
    f.seek(endOfBlock, 0)
    sys.exit(-1)
  return result

def extract1btype(f, name, baseOffset, endOfBlock):
  flag  = rU16(f)
  flagb = rU16(f)

  locb  = f.tell()
  
  val1 = rPackNum(f) ; val2 = 0
  if(f.tell() != endOfBlock):
    val2 = rPackNum(f)

  if(f.tell() == endOfBlock):
    return [['x', val1], ['y', val2]]

  f.seek(locb, 0)
  val1 = rU8(f)
  if(val1 == 0x00):
    val2 = rU8(f) ; subt = 0
    if(val2 not in [0x00, 0x80] and flag != 0x01):
      nil = rU16(f)  ; check(nil,  0x00, f, "Inner 1b type1")

    if(val2 == 0x80):
      size = rU32(f)
      dumpMp3(f, size, endOfBlock)
      return ["mp3", name]
    else:
      vals = []
      if(not (val1 == 0x00 and val2 == 0x00) or (flag == 0x01)):
        descCount = rPackNum(f)
        for j in range(descCount):
          qname = dumpBlock(f, name, baseOffset)
          val = dumpEntryValue(f, name + "/" + str(qname), baseOffset)
          vals.append([qname, val])

      if(f.tell() == endOfBlock):
        if(vals == []): return '-NONE-'
        else:           return vals
      else:
        imgname = name.replace('/', '.') + ".png"
        dumpImage(f, imgname)
        vals.append(['image', imgname])
        return vals
  else:
    blockval = val1
    return subBlock(f, val1, endOfBlock)

def computeName(image, name):
  name = name[0:name.rfind("/")+1]
  while(image[0:3] == "../"):
    name = name[0:-1]
    name = name[0:name.rfind("/")+1]
    image = image[3:]
  return name + image

def extract73type(f, name, baseOffset, endOfBlock):
  iname = rUStr(f)
  if(iname == "Shape2D#Convex2D"):
    count = rPackNum(f)
    return subBlock(f, count, endOfBlock)
  if(iname == "Shape2D#Vector2D"):
    val1 = rPackNum(f)
    val2 = rPackNum(f)
    return [["x", val1], ["y", val2]]
  if(iname == "Canvas"):
    space = rU16(f)  ; checkA(space, [0, 256], f)
    if(space == 256):
      nil = rU16(f)
      count = rU8(f)
      for i in range(count):
        qname = dumpBlock(f, name, baseOffset)
        val = dumpEntryValue(f, name + "/" + str(qname), baseOffset)
    imgname = name.replace('/', '.') + ".png"
    dumpImage(f, imgname)
    return ['image', imgname]
  if(iname == "UOL"):
    nil = rU8(f)
    image = dumpBlock(f, name, baseOffset)
    cName = computeName(image, name)
    return ['image*', cName]
  if(iname == "Sound_DX8"):
    nil = rU8(f)
    size = rPackNum(f)
    dumpMp3(f, size, endOfBlock)
    return ["mp3", name]
# ---------------------------------------------

def dumpBlock(f, name, baseOffset, endOfBlock = 0):
  global vals
  type = rU8(f)

  if   (type == 0x00): return extract00type(f)
  elif (type == 0x01): return extract01type(f, baseOffset)
  elif (type == 0x1b): return extract1btype(f, name, baseOffset, endOfBlock)
  elif (type == 0x73): return extract73type(f, name, baseOffset, endOfBlock)

def dumpEntryValue(f, name, baseOffset):
  global vals
  type = rU8(f)

  if   (type == 0x00): return "-NIL-"
  elif (type == 0x02): return extract02type(f)
  elif (type == 0x03): return extract03type(f)
  elif (type == 0x04): return extract04type(f)
  elif (type == 0x05): return extract05type(f)
  elif (type == 0x08): return extract08type(f, name, baseOffset)
  elif (type == 0x09): return extract09type(f, name, baseOffset)

def dumpFile(f, sname, baseOffset):
  global vals
  vals = {}

  flag = rU8(f)      ; check(flag, 0x73, f)
  imgName = rUStr(f) ; check(imgName, "Property", f)
  space = rU8(f)     ; check(space, 0x00, f, "File Outer Space")
  space = rU8(f)     ; check(space, 0x00, f, "File Outer Space 2")
  entries = rPackNum(f)
  
  vals = []
  for i in range(entries):
    name  = dumpBlock(f, sname, baseOffset)
    value = dumpEntryValue(f, str(name), baseOffset)
    vals.append([name, value])
  return vals


def dump():
  global dumpImages, dumpHTML
  global dumpDir, dumpDirBase
  f = open("文件名", "rb")

  if(dumpImages or dumpHTML):
    safe_mkdir(dumpDirBase)
    origstdout = sys.stdout

  header = extractHeader(f)
  DirTreeOffset = f.tell()

  global parsingFileTree
  parsingFileTree = 1
  dirTree = extractDirTree(f, DirTreeOffset)
  parsingFileTree = 0

  for i in range(len(dirTree["Files"])):
    file = dirTree["Files"][i]
    f.seek(file["Offset"], 0)

    if(dumpImages or dumpHTML):
      dumpDir = dumpDirBase + file["Name"].replace("/", ".") + "/"
      safe_mkdir(dumpDir)

    print "%4d: %s, %d, %d" % (i, repr(file["Name"])[1:-1], file["Size"], file["Offset"])

    vals = dumpFile(f, file["Name"], file["Offset"])
    vals = flatten(vals)
    if(dumpHTML):
      g = open(dumpDir + "index.html", "w")
      sys.stdout = g

      htmlOut(vals)

      g.close
      sys.stdout = origstdout
    else:
      textOut(vals)

dumpImages = 1
dumpHTML = 1

dumpDirBase = "dump/"
dumpDir     = dumpDirBase

dump()

把这段代码复制到记事本中,把代码中文件名改成你要提取的文件(列如:map.wz),然后把扩展名改为.py
然后安装python-2.4.2.msi(网上去搜)以支持代码运行,把你刚才保存的文件复制到冒险岛的目录中,双击打开此文件,系统自动提取,你只需要耐心的等,提取出来的文件保存在冒险岛的目录中多出来的一个文件夹中!

[1] [2] [3] [4] [5] 

 

发表评论
发表: 用户:  密码:   注册?  
验证码    
评论:

禁止表情
禁止UBB
禁止图片
识别链接
识别关键字
表  情
 

Copyright © 2006 All rights reserved. Design by huosoft

电话:13974847258    QQ群:7155339
Powered by L-Blog V-Blog 2004-2005