Skip to content

Instantly share code, notes, and snippets.

@randphu
Last active November 13, 2018 12:32
Show Gist options
  • Save randphu/5277346 to your computer and use it in GitHub Desktop.
Save randphu/5277346 to your computer and use it in GitHub Desktop.
extract buka manga archive (*.buka)
#!/usr/bin/env python3
'''
Layout of buka manga archives
Whole archive
| b"buka" | unknown (16 bytes) | manga title (c string) | entry table | file 1 | file 2 | ...
Entry table
| table size (uint32) | entry 1 | entry 2 | ... |
Entry
| offset (uint32) | size (uint32) | name (c string) |
Note
c string: null terminated, encoded in utf8.
unit32: 32 bit, unsigned, little endian.
table size contains the size of itself.
'''
import sys, os, struct
def readuint32(src):
buf = src.read(4)
return struct.unpack('<I', buf)[0]
def readcstring(src):
buf = b""
while True:
ch = src.read(1)
if ch[0] == 0:
return buf.decode('utf8'), len(buf) + 1
buf += ch
def readtable(src):
table = []
tsize = readuint32(src)
total = 4
while total < tsize:
offset = readuint32(src)
size = readuint32(src)
name, n = readcstring(src)
if name not in ["index2.dat", "chaporder.dat", "logo"]:
table.append((offset, size, name))
total += n + 8
return table
def copysection(dst, src, offset, size):
src.seek(offset)
dst.write(src.read(size))
def fmtsize(size):
for i in "kmgt":
size /= 1024
if size < 1024:
return "%.2f"%size + i
def extract(srcfile):
dstdir = os.path.join(os.path.dirname(srcfile), os.path.splitext(os.path.basename(srcfile))[0])
if not os.path.exists(dstdir):
os.mkdir(dstdir)
with open(srcfile, 'rb') as src:
if src.read(4) != b'buka':
print("%s: not a buka manga archive" % srcfile)
return
src.seek(20)
title, _ = readcstring(src)
table = readtable(src)
print("extract %s (%s) to %s/" % (srcfile, title, dstdir))
for offset, size, name in table:
dstfile = os.path.join(dstdir, name)
with open(dstfile, 'wb') as dst:
copysection(dst, src, offset, size)
print(" %s (%s)" % (name, fmtsize(size)))
for srcfile in sys.argv[1:]:
extract(srcfile)
@ClixTW
Copy link

ClixTW commented May 11, 2013

目前發現有完全不能解的文件(有你的小鎮)
更改副檔名為壓縮檔解壓縮失敗,
使用鏈接http://ppt.cc/Q_1t 内的軟体可以解,
但是檔案順序會跑掉,請問是哪裏發生了問題呢?
謝謝!

@randphu
Copy link
Author

randphu commented May 12, 2013

@jackie840301
这个脚本用了python3.x的特性,2.x是没法正确执行的
如果确保以上没错,再把出错信息、系统、漫画具体话数贴出来
Linux下测试结果,有你的小镇200-226话是可以解的

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment