NeoX 游戏引擎 NXPK 格式详解

[0x00 ~ 0x03] 4E 58 50 4B Magic Number: NXPK

[0x04 ~ 0x13] Not Important

[0x14 ~ 0x17] Pointer to List of Files: Little Endian

[0x18 ~ A Byte before List of Files] File Data

[First Byte of List of Files ~ EOF] List of Files

=====

List of Files:

Every file uses 7 Bytes

=====

File:

[0x00 ~ 0x03] Hash of Filename (Included Path): Little Endian

[0x04 ~ 0x07] File Offset: Little Endian

[0x08 ~ 0x0B] File Compressed Length (Acutual Length): Little Endian

[0x0C ~ 0x0F] File Original Length: Little Endian

[0x10 ~ 0x1B] Hash of File Content: Not Importan

And Not Important

=====

File Data:

File Data of every File is always stored regularly, e.g.

[LAST BUT TWO BYTES BEFORE EOF OF LAST FILE] ~

0xFF 0xFF 0x00 0x00 ~ 0xAA 0xAA 0xAA 0xAA ~

[FIFTH BYTE OF NEXT FILE]

File Data can be compressed or not compressed.

Compressed Data will use zlib with default setting (0x789C)

=====

All Hashes are calculated use a private algorithm from NetEase, it can even be implemented differently.

You can call it by DEBUGGING.

=====

A Example of Extracting Files using Python:

import os
import sys
import zlib

# File to open
# filename = "/home/test/TEST.NPK"
filename = input("File: ")

NPKSIGNATURE = NPKSIGNATURE = [0x4E, 0x58, 0x50, 0x4B]
all_bytes = open(args.input_file, "rb").read()
if list(all_bytes[:4]) != NPKSIGNATURE:
    print_fail("Failed to load file, bad signature")
    sys.exit()

print()
print("NeoX Package File: " + filename )
print("============================")
filecount = little_endian_to_int(all_bytes[4:6])
count = 0
listoffset = little_endian_to_int(all_bytes[0x14:0x18])
print("- Data Count: %d" % filecount)
print("- List Offset: " + hex_upper_with_0x(listoffset))
print("============================")
for i in range(listoffset, len(all_bytes), 28):
    filesign = all_bytes[i:i+4]
    fileoffset = little_endian_to_int(all_bytes[i+4:i+8])
    filelength = little_endian_to_int(all_bytes[i+8:i+12])
    fileoriginallength = little_endian_to_int(all_bytes[i+12:i+16])
    filehash = all_bytes[i+16:i+24]
    fileunknown = all_bytes[i+24:i+28]
    count += 1
    print("- File %.6d: " % count)
    print("-- Unknown: " + filesign.hex().upper())
    print("-- Offset: " + hex_upper_with_0x(fileoffset))
    print("-- Length: " + hex_upper_with_0x(filelength) + " (%d)" % filelength)
    print(
        "-- Original Length: " +
        hex_upper_with_0x(fileoriginallength) +
        " (%d)" % fileoriginallength
    )
    print("-- Hash: " + filehash.hex().upper())
    print("-- Unknown: " + fileunknown.hex().upper())
    if args.pause:
        pause()
    filecontent = all_bytes[fileoffset:fileoffset + filelength]
    if args.content:
        print_bytes(filecontent)
    # if extract_flag:
    if True:
        print()
        print("-- = Start Extraction =")
        if filelength != fileoriginallength:
            filecontent = zlib.decompress(filecontent)
            print("\nDecompressed: ")
            if args.content:
                print_bytes(filecontent)
            # extracttype = get_ext_by_filecontents(filecontent)
            extracttype = "bin"
            print()
        extractname = (
            os.path.basename(filename) +
            "." + filesign.hex().upper() +
            "." + extracttype
        )
        extractpath = os.path.join(extract_folder, extractname)
        open(extractpath, "wb").write(filecontent)
        print("--- Saved as " + extractpath)
    print()

=====

以上です。

发布于 2017-01-23