光隙解语有大佬会解包嘛

光隙解语有大佬会解包嘛

import io
import os
import gzip
import struct
from PIL import Image
import texture2ddecoder

def read_rb_file(wj):
    with open(wj, 'rb') as xa:
        sj = xa.read()
    return sj

def save_rb_file(sj, wj):
    with open(wj, 'wb') as xa:
        xa.write(sj)

def xxtea_decrypt_file(datain: bytearray):
    dyq = bytearray(b'\x52\x45\x46\x3A\x00\x00\x00\x02')
    dyk = bytearray("A8ZXC4a4-0cd7-47", 'utf-8')

    def _long2str(v, w):
        n = (len(v) - 1) << 2
        if w:
            m = v[-1]
            if (m < n - 3) or (m > n):
                return ''
            n = m
        s = struct.pack('<%iL' % len(v), *v)
        return s[0:n] if w else s

    def _str2long(s, w):
        n = len(s)
        m = (4 - (n & 3) & 3) + n
        s = s.ljust(m, b"\0")
        v = list(struct.unpack('<%iL' % (m >> 2), s))
        if w:
            v.append(n)
        return v

    def decrypt(str, key):
        if str == '':
            return str
        _DELTA = 0x9E3779B9
        v = _str2long(str, False)
        k = _str2long(key.ljust(16, b"\0"), False)
        n = len(v) - 1
        z = v[n]
        y = v[0]
        q = 6 + 52 // (n + 1)
        sum = (q * _DELTA) & 0xffffffff
        while (sum != 0):
            e = sum >> 2 & 3
            for p in range(n, 0, -1):
                z = v[p - 1]
                v[p] = (v[p] - ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))) & 0xffffffff
                y = v[p]
            z = v[n]
            v[0] = (v[0] - ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[0 & 3 ^ e] ^ z))) & 0xffffffff
            y = v[0]
            sum = (sum - _DELTA) & 0xffffffff
        return _long2str(v, True)

    def xxtea_decrypt(databytes: bytearray, decrypt_len: int, key: bytearray):
        datasrc_todecrypt = databytes[:decrypt_len]
        decrypted_bytes = decrypt(datasrc_todecrypt, key)
        if isinstance(decrypted_bytes, str):
            decrypted_bytes = decrypted_bytes.encode()
        data_result = b''.join((decrypted_bytes, databytes[decrypt_len:]))
        return data_result

    signlen = len(dyq)
    datasrc = datain[signlen:]
    key = dyk.ljust(16, b'\0')
    assert len(key) == 16
    datasrc_clean = datasrc
    decrypt_len = datasrc[5] | ((datasrc[4] | ((datasrc[3] | (datasrc[2] << 8)) << 8)) << 8)
    assert len(datasrc_clean) >= 0
    return xxtea_decrypt(datasrc_clean, decrypt_len, key)

def gzip_binary_data_decompression(sj, hz, dc):
    if sj[:2] == b'\x1f\x8b':
        wj = io.BytesIO(sj)
        with gzip.GzipFile(fileobj=wj, mode='rb') as xa:
            jy = xa.read()
    else:
        jy = sj
    if jy[:4] == b'\x13\xAB\xA1\x5C':
        aa = int.from_bytes(jy[4:5], byteorder='little', signed=False)
        ab = int.from_bytes(jy[5:6], byteorder='little', signed=False)
        ac = int.from_bytes(jy[7:9], byteorder='little', signed=False)
        ad = int.from_bytes(jy[10:12], byteorder='little', signed=False)
        jy = texture2ddecoder.decode_astc(jy[16:], ac, ad, aa, ab)
        if hz.lower() == '.jpg':
            tp = Image.frombytes("RGBA", (ac, ad), jy, 'raw', ("BGRA")).convert("RGB")
            tp.save(dc, format="JPEG", quality=90)
        else:
            tp = Image.frombytes("RGBA", (ac, ad), jy, 'raw', ("BGRA"))
            tp.save(dc, format='PNG')
    else:
        save_rb_file(jy, dc)

def light_gap_interpretation(wj, hz, dc):
    if wj[:8] == b'\x52\x45\x46\x3A\x00\x00\x00\x02':
        gzip_binary_data_decompression(xxtea_decrypt_file(bytearray(wj)), hz, dc)
    elif wj[:2] == b'\x1f\x8b' or wj[:4] == b'\x13\xAB\xA1\x5C':
        gzip_binary_data_decompression(wj, hz, dc)

def get_file_list(ml, hz='*', pd=True):
    lx = hz.lower()
    tl = {
        '<': lambda xd: '.' not in xd,
        '.*': lambda xd: '.' in xd,
        '*': lambda xd: True,
    }
    tj = tl.get(hz, lambda xd: xd.lower().endswith(lx))
    if pd:
        lb = [os.path.join(xa, xd) for xa, xb, xc in os.walk(ml) for xd in xc if tj(xd)]
    else:
        lb = [xa.path for xa in os.scandir(ml) if xa.is_file() and tj(xa.name)]
    return lb

def light_gap_interpretation_decrypt(lj):
    lb = get_file_list(lj, '*')
    for xb in lb:
        if not xb.lower().endswith('.py'):
            light_gap_interpretation(read_rb_file(xb), os.path.splitext(os.path.basename(xb))[-1], xb)

if __name__ == '__main__':
    light_gap_interpretation_decrypt(os.getcwd())

将资源都放在与脚本同级的一个文件夹下,脚本会进行xxtea解密和astc转换,时间会有点长,依赖就Pillow和texture2ddecoder

light_gap_interpretation_TW_list.zip (376.7 KB)
台服的资源列表,有需求的可以自己下

大佬,太感谢你了。

捕获
这是没下载依赖麽

终端执行pip install Pillow

C:\Users\admin>pip install Pillow
Fatal error in launcher: Unable to create process using ‘“d:\huanjin\python.exe” “D:\huanjin\Scripts\pip.exe” install Pillow’: ???

你这是环境有问题啊
python -m install Pillow
这样执行我看看

C:\Users\admin>python -m install Pillow
D:\python\python.exe: No module named install

python -m pip install  Pillow

试试,通宵完脑子抽风,忘记加pip了(


是这样

C:\Users\admin\Desktop\gx>python 123.py
Traceback (most recent call last):
File “C:\Users\admin\Desktop\gx\123.py”, line 6, in
import texture2ddecoder
ModuleNotFoundError: No module named ‘texture2ddecoder’

这个依赖要怎么安装 :joy:

照葫芦画瓢啊


你是一点不看我写的啊,报错不会的直接谷歌比我回答你快多了,秒出结果


大佬,这个要怎么播放啊

你这,要么去映射表还原名称,要么用我那个资源列表来下(

import os
import requests
from urllib.parse import urlparse
from tqdm import tqdm
from multiprocessing import Pool

output_folder = 'resource'
if not os.path.exists(output_folder):
    os.makedirs(output_folder)

num_processes = 256

download_list = []
with open('light_gap_interpretation_TW_list.txt', 'r', encoding='utf-8') as file:
    for line in file:
        parts = line.strip().split('<')
        if len(parts) == 3:
            url, location, size = parts
            download_list.append((url.strip(), location.strip(), int(size)))

def download_file(url_location_size):
    url, location, size = url_location_size
    filename = os.path.join(output_folder, location)

    if not os.path.exists(filename) or os.path.getsize(filename) != size:
        if not os.path.exists(os.path.dirname(filename)):
            os.makedirs(os.path.dirname(filename))
        print(f"Downloading {location}...")
        response = requests.get(url, stream=True)
        with open(filename, 'wb') as file, tqdm(
                desc=location, total=size, unit="B", unit_scale=True) as bar:
            for data in response.iter_content(chunk_size=1024):
                file.write(data)
                bar.update(len(data))
        return size
    else:
        print(f"Skipping {location} (already exists)")
        return 0

if __name__ == '__main__':
    total_size = 0
    with Pool(num_processes) as pool:
        results = pool.map(download_file, download_list)
        total_downloaded = sum(1 for result in results if result > 0)
        total_size = sum(results)

    print(f"Downloaded {total_downloaded} files with a total size of {total_size / (1024 * 1024):.2f} MiB")


大佬这个资源列表怎么用,我把代码保存py跟资源列表放一起,运行他会闪退


大佬可以了,就是感觉下的不全