2014-5-11 16:05 /
如果你想直接解析汉化组的文本(或者后期的Siglus开发的游戏),我只能告诉你,这个程序是解析不了的。
但是脚本格式是不变的。只是字符串会多一层128bit的加密。
而且这个128Bit的key经常改变233
如果要拆后期的文本,将每个wchar进行解密就行了=。=

另外,如果在一般的文本编辑器下看见的是乱码(因为没Signature),试试UTF-16LE。

#include <cstdio>
//#include <cstring>
#include <windows.h>
#include <wchar.h>
#include <locale.h>

using namespace std;

typedef struct ScriptHdr
{
        DWORD ScriptHdrLen;
        DWORD OperationOffset;
        DWORD OperationCount;
        DWORD StringTableOffset;
        DWORD StringTableCount;
        DWORD OriginalStringOffset;
        DWORD OriginalStringCount;
        DWORD Var1PairOffset;
        DWORD Var1PairCount;
        DWORD Var2PairOffset;
        DWORD Var2PairCount;
        DWORD VarArray[17];
        DWORD Var3PairOffset;
        DWORD Var3PairCount;
        DWORD Var4PairOffset;
        DWORD Var4PairCount;
};

typedef struct InfoPair
{
        DWORD Offset;
        DWORD Count;
};

int main(int argc, char **argv)
{
        setlocale( LC_CTYPE,"chs");
        if(argc < 1)
        {
                printf("Usage : %s [ScriptFile]\n",argv[0]);
                exit(1);
        }
        FILE *fin = fopen(argv[1],"rb");
        char *FileName = new char[strlen(argv[1])+strlen("_str.txt")+1];
        sprintf(FileName,"%s_str.txt",argv[1]);
       
        WCHAR FileNameW[MAX_PATH];
        memset(FileNameW,0,MAX_PATH*2);
        MultiByteToWideChar(CP_UTF8,0,FileName,strlen(FileName),FileNameW,strlen(FileName)*2);
       
        FILE *fout = _wfopen(FileNameW,L"wb");
       
        fseek(fin,0,SEEK_END);
        DWORD dwFileSize=ftell(fin);
        rewind(fin);
        char *pFile=new char [dwFileSize];
        fread(pFile,dwFileSize,1,fin);
        fclose(fin);
       
        ScriptHdr _hdr;
        DWORD iPos = 0;
        memcpy(&_hdr,pFile,0x84);
        printf("SiglusEngine Script Info [%s]\n",argv[1]);
    /**********************************************************/
    InfoPair StrList[_hdr.StringTableCount];
    memcpy(&StrList,(pFile+_hdr.StringTableOffset),_hdr.StringTableCount * 8);
    for(DWORD Line = 0;Line < _hdr.StringTableCount; Line++)
        {
            fprintf(fout,"<%08d>",Line);
                WCHAR WStrBuffer[MAX_PATH];
                memset(WStrBuffer,0,MAX_PATH*2);
                LPWSTR StrOffset = LPWSTR (pFile+iPos);
                wcsncpy(WStrBuffer,StrOffset,StrList[Line].Count);
        wprintf(L"%s\n",WStrBuffer);
    }
       
    fclose(fout);
        return 0;
}
#1 - 2017-2-5 12:10
(Hentai Typing)
顺便扔个python版,Rewrite+测试成功:
https://github.com/tuxzz/RewriteTool

ssmanager.py:

import struct
import io

def xorCrypt(x, key):
    key *= 0x7087
    key &= 0xFFFFFFFF
    o = bytearray(len(x))
    for i in range(0, len(x) - 1, 2):
        v2 = (key >> 8) & 0xFF
        v1 = key & 0xFF
        o = x ^ v1
        o[i + 1] = x[i + 1] ^ v2
    return bytes(o)

class Entry:
    def __init__(self, data):
        self.pos, self.length = struct.unpack("<II", data)

    @staticmethod
    def pack(pos, length):
        return struct.pack("<II", pos, length)

class SSManager:
    def __init__(self):
        self.signature = bytes((0x00, 0x53, 0x69, 0x67, 0x6C, 0x75, 0x73, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72))

    def load(self, data):
        assert(isinstance(data, bytes))
        self.data = data
        self.firstPos = len(data)

        offsetTable = Entry(data[0xC:0xC + 8])
        stringTable = Entry(data[0x14:0x14 + 8])

        content = []
        for i in range(stringTable.length):
            offset = offsetTable.pos + i * 8
            strEntry = Entry(data[offset:offset + 8])
            pos = (strEntry.pos * 2) + stringTable.pos # *2 because of utf-16
            if(pos < self.firstPos):
                self.firstPos = pos
            strData = xorCrypt(data[pos:pos + strEntry.length * 2], i)
            content.append(strData.decode("utf-16-le"))
        self.stringList = content
        self.__stringCount__ = len(self.stringList)

    def dump(self):
        base = bytearray(self.data[:self.firstPos] if(self.hasSignature()) else self.data)
        offsetTable = Entry(base[0xC:0xC + 8])
        assert(self.__stringCount__ == offsetTable.length)
        assert(len(self.stringList) == self.__stringCount__)

        base[0x14:0x14 + 4] = struct.pack("<I", len(base))
        stream = io.BytesIO()
        iTotal = 0
        for i, s in enumerate(self.stringList):
            offset = offsetTable.pos + i * 8
            base[offset:offset + 8] = Entry.pack(iTotal, len(s))
            stream.write(xorCrypt(s.encode("utf-16-le"), i))
            iTotal += len(s)
        return bytes(base + stream.getvalue() + self.signature)

    def hasSignature(self):
        return self.data[-len(self.signature):] == self.signature