标题: ls11格式详解
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-2 20:41 资料 短消息 看全部作者
这么复杂的解码都能研究出来,van真是厉害

Maxwell的解述很清晰,很容易明白解码过程。

我试着按照Maxwell所说的解码过程逆了一下,但发现难实现编码过程呀。基本上编码过程以lz为主,大概应该是这样的过程吧:

1. 按照LZ算法,适当选择缓冲区N的大小和每次处理的块F的大小;

2. 在缓冲区N中寻找与块F相匹配的最大字串,并记录下匹配的位置和匹配长度,分别记为i和l;(前面这两步就是标准的lz77压缩算法,可以参看lz77);

3. 对于得到的i和l这两个数,需要做一些判断。如果l <= 3,那么对当前处理的字符就直接采用编码字典来进行编码,此时i的值修正为当前字符在编码字典中的索引;否则,i = i + 256; l = l - 3;

4. 对i和l进行编码。如果i <= 256,那么只对i进行编码,l不编码;否则i和l都编码。对i和i的编码方法就是Maxwell所说的将二进制数分解成两个数的方法。实际上,对i和l的编码页可以这样描述:先将该数表示成二进制(前面不带0),然后数bit个数,假设为n,然后输出n-2个连1加1个0,并用原数减掉11...0(n-2个1连1和1个0),两部分合起来就是i或ll的编码(实际上是把i和l占用的bit长度信息编码进去了)。对i和l编码就做为输出结果。(压缩本质:用i和l的编码替换了原来的串中的最大匹配串)

大概过程应该就是这样,但有一些细节问题:N和F的大小不知道;编码字典不知道;i和l同时编码应满足的条件不知;i和l的编码方法。


精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-2 21:57 资料 短消息 看全部作者
刚才细推了一下,发现最关键的是不能从解码过程看出滑动窗口的长度N和编码时每次处理的块长度F


精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-2 22:07 资料 短消息 看全部作者


QUOTE:
原帖由Maxwell于2004-12-02, 22:02:25发表
我想这两个参数都可以定为整个原文长度,在实际的压缩中效率是可以接受的。另外修改一点是压缩是以一段话为单位的,而字典是整个文件公用的,应该是对文件中所有的压缩段用过lz之后再统计频率的。

编码字典与解码字典可能是同一个字典么
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-3 04:17 资料 短消息 看全部作者
看题目。

说的就是ls11压缩文件格式的解码方法。什么是ls11压缩文件?看看前面的帖子。比如san9中m_msg.s9、m_rtdn.s9就是用这种算法压缩的
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-3 13:58 资料 短消息 看全部作者


QUOTE:
原帖由东方无翼于2004-12-03, 8:22:24发表
刚才我试了van解出来的M_Msg.s9  怎么也出错进不了游戏?不是我的san9有问题吧。

并且van能不能解释一下压缩后长度和原文长度后面那8个字节的意义?
其中前四字节,Msg文件都是0000 0120,图像文件有0000 0103和0000 0102(是吧,Maxwell来看看对不对)。
后四个字节在van的M_Msg.s9里是CCCC CCCC。是怎么算出来的?

我试了也不行;另外试了我自己解出来的也不行,都会出错。

似乎游戏程序认定M_msg.s9就是压缩过的,而并没有去比较哪两个长度,所以一读进来就立刻解压,殊不知本来就解压过了。
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-3 14:12 资料 短消息 看全部作者


QUOTE:
原帖由Maxwell于2004-12-03, 14:02:48发表
后面的CCCCCCCC是不对的,应该改成00000000,这样那个m_msg应该就能能用了
van说了这么句话,你试试看。

我解压出来的,后面就是0,其余跟van的一样。

另,我还试过改原m_msg.s9中的压缩长度47EEF和为压缩长度9DE3A,发现只有改9DE3A才有影响,说明程序根本没有理会前面那个压缩后长度47EEF,而是直接用文件长度-0x120来计算压缩后长度。感觉san9.exe就是认定那个文件是压缩过的。
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-3 14:15 资料 短消息 看全部作者
尝试了一下压回去,却不能还原   

可能编码方法不太正确
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-3 14:20 资料 短消息 看全部作者


QUOTE:
原帖由Maxwell于2004-12-03, 14:14:20发表

QUOTE:
原帖由gameplore于2004-12-03, 14:12:16发表
[quote]原帖由Maxwell于2004-12-03, 14:02:48发表
后面的CCCCCCCC是不对的,应该改成00000000,这样那个m_msg应该就能能用了
van说了这么句话,你试试看。

我解压出来的,后面就是0,其余跟van的一样。

另,我还试过改原m_msg.s9中的压缩长度47EEF和为压缩长度9DE3A,发现只有改9DE3A才有影响,说明程序根本没有理会前面那个压缩后长度47EEF,而是直接用文件长度-0x120来计算压缩后长度。感觉san9.exe就是认定那个文件是压缩过的。

那你调整一下0120这个数值行不行?让它计算出来的压缩长度等于未压缩长度。 [/quote]
改那个数的确有影响,如果改成0,进入游戏后什么文字都没有了。

0x120的含义应该是:压缩文本起始地址偏移。

据猜测san9.exe处理m_msg的过程:
1)读入m_msg.s9;

2)读取为压缩长度,0x9DE3A,并分配这么长的buffer;

3)获取文件长度_get_file_length,用文件长度-偏移;

4)从偏移处开始解压,共解压文件长度-偏移这么长。
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-3 14:24 资料 短消息 看全部作者


QUOTE:
原帖由Maxwell于2004-12-03, 14:20:01发表

QUOTE:
原帖由gameplore于2004-12-03, 14:15:37发表
尝试了一下压回去,却不能还原   

可能编码方法不太正确  

压缩算法可能有问题吧,我一直没有仔细研究lz系列算法,只是大致明白原理,从来没有写过代码。lz是个贪心算法吧?不一定能够达到最大压缩率是吗?

我用的是lz77的方法,压回去后比原m_msg.s9稍小。但是由于寻找重复串时全文本比较,因此非常非常地慢。估计原来的压缩方法并没有这么慢。
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-3 14:43 资料 短消息 看全部作者
// Msg_Codec.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <crtdbg.h>

#ifndef BYTE
typedef unsigned char BYTE;
#endif

static const int DICT_LEN = 0x100;
static const int ACTUAL_LEN = 0x9DE3A;

class CLS11
{
// Operations
public:
    //---------------------------------------------------------------------------
    // Inputs:  pDict       -- Pointer to the dictionary.
    //          pSrc        -- Pointer to source data buffer.
    //          pDest       -- Pointer to destination data buffer.
    //          nLenActual  -- Length of valid source data.
    //          nLenSrc     -- Length of source data buffer.
    //          nLenDest    -- Length of destination data buffer.
    //          bCompress   -- true if LZ compression needs to be taken.
    // Returns: The length of encoded data.
    // Summary: Call this method to encode specified data with LS11.
    //--------------------------------------------------------------------------
    int Encode( BYTE *pDict, const BYTE *pSrc, BYTE *pDest, int nLenActual, int nLenSrc, int nLenDest, bool bCompress = false );
   
    //--------------------------------------------------------------------------
    // Inputs:  pDict       -- Pointer to the dictionary.
    //          pSrc        -- Pointer to source data buffer.
    //          pDest       -- Pointer to destination data buffer.
    //          nLenSrc     -- Length of source data buffer.
    //          nLenDest    -- Length of destination data buffer.
    //          nLenActual  -- Length of original data.
    // Returns: The length of decoded data.
    // Summary: Call this method to decode LS11-encoded data. This procedure is
    //          based on the code written by Maxwell & van.
    //--------------------------------------------------------------------------
    int Decode( BYTE *pDict, const BYTE *pSrc, BYTE *pDest, int nLenActual, int nLenSrc, int nLenDest );

// Properties
protected:
    int m_srcpos;
    int m_destpos;
    int m_bitpos;
    BYTE *m_pDest;
    const BYTE *m_pSrc;

// Implementations
protected:   
    void SetCode( unsigned int code );
    unsigned int GetCode( );
    void ReorderDict( BYTE const *pDictSrc, BYTE *pDictDest, int nLenDict );   
   
} ;

int CLS11::Encode( BYTE *pDict, const BYTE *pSrc, BYTE *pDest, int nLenActual, int nLenSrc, int nLenDest, bool bCompress )
{
    int off, len, lenmax, offmax;
    BYTE *pNewDict = new BYTE[DICT_LEN];
   
    m_pDest = pDest;
    m_pSrc = pSrc;
    m_srcpos = 0;
    m_destpos = 0;
    m_bitpos = 0;
        
    _ASSERT( nLenActual <= nLenSrc && pNewDict );

    memset( m_pDest, 0, nLenDest );
    ReorderDict( pDict, pNewDict, DICT_LEN );

    // If no compress needs to be taken, use dictionary only.
    if( !bCompress )
    {
        while( m_srcpos < nLenActual && m_destpos < nLenDest )
        {
            SetCode( pNewDict[m_pSrc[m_srcpos++]] );
        }
    }
    else
    {
        while( m_srcpos < nLenActual && m_destpos < nLenDest )
        {           
            // Scan whole text
            for( off = 1, lenmax = 0, offmax = 1; off <= m_srcpos; off++ )
            {
                for( len = 0; len + m_srcpos < nLenSrc && m_pSrc[m_srcpos - off + len] == m_pSrc[m_srcpos + len]; len++ );                        
                if( len > lenmax )
                {
                    lenmax = len;
                    offmax = off;
                }
            }
            // Replace the duplicated string with two number: offmax + 256 and lenmax - 3
            if( lenmax >= 3 )
            {
                SetCode( offmax + 256 );
                SetCode( lenmax - 3 );

                m_srcpos += lenmax;
            }
            else
            {
                SetCode( pNewDict[m_pSrc[m_srcpos++]] );
            }        
        }
    }

    while( m_bitpos )
    {
        m_pDest[m_destpos] <<= 1;
        m_bitpos++;
        if( m_bitpos > 7 )
        {
            m_bitpos = 0;
            m_destpos++;
            break;
        }
    }   

    delete [] pNewDict;
    return m_destpos;
}
int CLS11:ecode( BYTE *pDict, const BYTE *pSrc, BYTE *pDest, int nLenActual, int nLenSrc, int nLenDest )
{
    unsigned int code, off, len;   

    m_pSrc = pSrc;
    m_destpos = 0;
    m_srcpos = 0;
    m_bitpos = 7;

    _ASSERT( nLenActual <= nLenDest );
    while( m_srcpos < nLenSrc && m_destpos < nLenActual )
    {
        code = GetCode( );  
        if( code < 256 )
        {
            pDest[m_destpos++] = pDict[code];
        }
        else
        {            
            off = code - 256;
            len = GetCode( ) + 3;
            for( unsigned int i = 0; i < len && m_destpos < nLenDest; i++ )
            {
                pDest[m_destpos] = pDest[m_destpos - off];
                m_destpos++;
            }
        }
    }
    // Padding
    while( m_destpos < nLenActual )
    {
        pDest[m_destpos++] = pDict[0];
    }
    return m_destpos;
}

void CLS11::SetCode( unsigned int code )
{
    unsigned int temp, code1, code2;
    int len, i;
    temp = code;
    len = 0;
    code1 = 0;        
    // How many valid bits are contained in variable code
    while( temp > 1)
    {
        temp >>= 1;
        code1 = (code1 << 1) | 0x01;
        len++;
    }     
    if( (code1 << 1) <= code )
    {
        len++;
        code1 = code & (~1);
    }
    else
        code1--;

    code2 = code - code1;

    // Output bits of code1
    for( i = len - 1; i >= 0; i-- )
    {
        m_pDest[m_destpos] = (m_pDest[m_destpos] << 1) | (code1 >> i);
        m_bitpos++;
        if( m_bitpos > 7)
        {
            m_bitpos = 0;
            m_destpos++;
        }
    }
    // Output bits of code2
    for( i = len - 1; i >= 0; i-- )
    {
        m_pDest[m_destpos] = (m_pDest[m_destpos] << 1) | (code2 >> i);
        m_bitpos++;
        if( m_bitpos > 7)
        {
            m_bitpos = 0;
            m_destpos++;
        }
    }
}
unsigned int CLS11::GetCode( )
{
    unsigned int code1 = 0, code2 = 0;
    int len = 0, bit;
    do
    {
        bit = (m_pSrc[m_srcpos] >> m_bitpos) & 0x01;
        code1 = (code1 << 1) | bit;
        len++;
        m_bitpos--;
        if( m_bitpos < 0 )
        {
            m_bitpos = 7;
            m_srcpos++;
        }
    } while( bit );
    for( int i = 0; i < len; i++ )
    {
        bit = (m_pSrc[m_srcpos] >> m_bitpos) & 0x01;
        code2 = (code2 << 1) | bit;
        m_bitpos--;
        if( m_bitpos < 0 )
        {
            m_bitpos = 7;
            m_srcpos++;
        }
    }

    return (code1 + code2);
}

void CLS11::ReorderDict( const BYTE *pDictSrc, BYTE *pDictDest, int nLenDict )
{
    for( int i = 0; i < nLenDict; i++ )
    {
        for( int j = 0; j < nLenDict; j++ )
        {
            if( pDictSrc[j] == i )
            {
                pDictDest = j;
                break;
            }
        }        
    }
}
// Big-endian to Little-endian or reverse
int Convert( int x )
{
    int ret = 0;
    BYTE *p = (BYTE *)(&x);
    ret = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];   
    return ret;
}
void TestEncode()
{
    CLS11 ls11;
    BYTE *pDict, *pSrc, *pDest;

    int l1, l2, off, zero = 0;// Big-endian values

    pDict = new BYTE[DICT_LEN];   

    FILE *fin = fopen("C:/code/m_msg_dec.s9", "rb");
    FILE *fout = fopen("C:/code/m_msg_enc1.s9", "wb");
    FILE *fout2 = fopen("C:/code/m_msg_enc2.s9", "wb");

    _ASSERT( fin && fout && fout2 && pDict );

    fread( pDict, 0x10, 1, fin );
    fwrite( pDict, 0x10, 1, fout );
    fwrite( pDict, 0x10, 1, fout2 );

    fread( pDict, 0x100, 1, fin );
    fwrite( pDict, 0x100, 1, fout );   
    fwrite( pDict, 0x100, 1, fout2 );

    fread( &l1, 4, 1, fin );   
    pSrc = new BYTE[Convert(l1)];

    fread( &l2, 4, 1, fin );   
    pDest = new BYTE[Convert(l2)];

    fread( &off, 4, 1, fin );   

    _ASSERT( pSrc && pDest );
        
    fseek( fin, Convert(off), SEEK_SET );
    fseek( fout, Convert(off), SEEK_SET );   

    fread( pSrc, Convert(l1), 1, fin );   
    int nLen = ls11.Encode( pDict, pSrc, pDest, ACTUAL_LEN, Convert(l1), Convert(l2), false );
    fwrite( pDest, nLen, 1, fout );

    fseek( fout, 0x110, SEEK_SET );
    l1 = Convert( nLen );   
    fwrite( &l1, 4, 1, fout );
    fwrite( &l2, 4, 1, fout );   
    fwrite( &off, 4, 1, fout );
    fwrite( &zero, 4, 1, fout );

   
    nLen = ls11.Encode( pDict, pSrc, pDest, ACTUAL_LEN, Convert(l2), Convert(l2), true );   
    fseek( fout2, Convert(off), SEEK_SET );
    fwrite( pDest, nLen, 1, fout2 );

    fseek( fout2, 0x110, SEEK_SET );
    l1 = Convert( nLen );   
    fwrite( &l1, 4, 1, fout2 );
    fwrite( &l2, 4, 1, fout2 );   
    fwrite( &off, 4, 1, fout2 );
    fwrite( &zero, 4, 1, fout2 );

    fclose( fin );
    fclose( fout );
    fclose( fout2 );

    delete [] pDict;
    delete [] pSrc;
    delete [] pDest;
}

void TestDecode()
{
    CLS11 ls11;
    BYTE *pDict, *pSrc, *pDest;

    int l1, l2, off, zero = 0;

    pDict = new BYTE[DICT_LEN];   

    FILE *fin = fopen("I:/San9pk/m_msg.s9", "rb");
    FILE *fout = fopen("C:/code/m_msg_dec.s9", "wb");

    _ASSERT( fin && fout && pDict );

    fread( pDict, 0x10, 1, fin );
    fwrite( pDict, 0x10, 1, fout );

    fread( pDict, 0x100, 1, fin );
    fwrite( pDict, 0x100, 1, fout );   

    fread( &l1, 4, 1, fin );
    l1 = Convert( l1 );
    pSrc = new BYTE[l1];

    fread( &l2, 4, 1, fin );
    l2 = Convert( l2 );
    pDest = new BYTE[12];

    fread( &off, 4, 1, fin );
    off = Convert( off );

    _ASSERT( pSrc && pDest );
        
    fseek( fin, off, SEEK_SET );
    fseek( fout, off, SEEK_SET );

    fread( pSrc, 0x47EEF, 1, fin );

    int nLen = ls11.Decode( pDict, pSrc, pDest, ACTUAL_LEN, l1, l2 );

    fwrite( pDest, nLen, 1, fout );

    fseek( fout, 0x110, SEEK_SET );
    l1 = l2 = Convert( nLen );
    fwrite( &l1, 4, 1, fout );
    fwrite( &l2, 4, 1, fout );
    off = Convert( off );
    fwrite( &off, 4, 1, fout );
    fwrite( &zero, 4, 1, fout );

    fclose( fin );
    fclose( fout );

    delete [] pDict;
    delete [] pSrc;
    delete [] pDest;
}



int _tmain(int argc, _TCHAR* argv[])
{
    //TestDecode();
    TestEncode();
    return 0;
}
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-3 14:51 资料 短消息 看全部作者
根据解码时的描述:
向回偏移a个位置后复制b个字节

所以猜测编码时采用的是类似于lz77的那种方法,不过原来的编码可能没有全文本扫描匹配,而只在前后一定长度范围内扫描。。。
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-4 00:50 资料 短消息 看全部作者
前面的压缩编码方法有点小bug,调试后已经修正。解码出来的文件再压缩回去之后,san9.exe都能够正确识别。

附件:

m_msg_dec.s9: 从原来的m_msg.s9中解压出来的,并改了两个人的名字:
曹操==>嬴政;吕布==>项羽

m_msg_enc1.s9:采用最低压缩率(没有用lz扫描,而只用了字典)对m_msg_dec.s9重新压缩后的文件;

m_msg_end2.s9:采用最高压缩率(全文本lz扫描,对于lz来说应该是最高了)对m_msg_dec.s9重新压缩后的文件。

把m_msg_enc1.s9和m_msg_enc2.s9改名为m_msg.s9后放回去,游戏程序都能正确解压,而且进入游戏发现曹操和吕布的名字变成嬴政和项羽了  

很早之前,我就一直在考虑怎么改历史武将的姓名,无奈自己水平有限,很长时间以来都不知道怎么改。幸好得到van,maxwell等的帮助,今日才得以实现。   

另外还有一个问题,虽然名字是改了,可是旗子怎么还是没变呢?新武将的话,旗子应该是和姓有关系的,怎么历史武将的旗子不是根据姓名来确定的么?

附件装不下,分3个帖子


附件: m_msg_dec.rar (2004-12-4 00:50, 173.47 K)
该附件被下载次数 441
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-4 00:52 资料 短消息 看全部作者
m_msg_enc2.s9


附件: m_msg_enc2.rar (2004-12-4 00:52, 239.26 K)
该附件被下载次数 377
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-4 00:56 资料 短消息 看全部作者
m_msg_enc1_part1.s9


附件: m_msg_enc1.part1.rar (2004-12-4 00:56, 200 K)
该附件被下载次数 307
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-4 00:58 资料 短消息 看全部作者
m_msg_enc1 part2


附件: m_msg_enc1.part2.rar (2004-12-4 00:58, 123.7 K)
该附件被下载次数 305
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-4 15:28 资料 短消息 看全部作者


QUOTE:
原帖由Maxwell于2004-12-04, 11:07:38发表
原来gameplore是用vc的高手呀,以后这个版上有人请教vc的问题你可要出手呀。

高手不敢当,不过欢迎讨论
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2004-12-4 15:35 资料 短消息 看全部作者


QUOTE:
原帖由van于2004-12-04, 12:18:19发表
类似于三十,游戏里只支持一部分姓,所以对于历史武将,旗帜编号应该存在于剧本中

这就试一下
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2005-4-1 19:31 资料 短消息 看全部作者


QUOTE:
原帖由三国在飞于2005-04-01, 18:52:34发表
好人做到底,把三九的也做出来吧!

作个能修改三九的MSG来,不能让三十专美于前啊!

代码有啦,怎么没有人帮忙做个出来呢???

三九的msg好像不是很有规律

直接用ultraedit改改就可以啦
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2005-4-5 18:03 资料 短消息 看全部作者


QUOTE:
原帖由三国在飞于2005-04-01, 22:15:56发表
不行,全是看不懂的乱码,怎么改,另外,乱改后游戏都进不去啊!

可以改的

乱码是因为解压缩之后还是BIG5,要用AppLocale启动UE32,选择繁体中文语言(BIG5),然后再打开文件解压缩后的文件,就可以看见文字了。

至于输入,随便哪一个能输入BIG5码的输入法都可以
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2005-4-14 23:52 资料 短消息 看全部作者


QUOTE:
原帖由三国在飞于2005-04-05, 18:13:18发表

QUOTE:
原帖由gameplore于2005-04-05, 18:03:46发表
可以改的

乱码是因为解压缩之后还是BIG5,要用AppLocale启动UE32,选择繁体中文语言(BIG5),然后再打开文件解压缩后的文件,就可以看见文字了。

至于输入,随便哪一个能输入BIG5码的输入法都可以

我做不出来的,不会解压啊,更不要说解压更改后再压缩回去!你能不能帮忙做个出来呢(修改器)

原来是不会解压缩啊,其实前面的代码已经给出了。这里附上了一个简单的压缩/解压缩程序

我没有测试过,只在以前试过修改人名是可以的。完整的源代码也附上,想做完整的msg修改器的朋友可以以此为基础

程序仅仅提供压缩、解压缩功能,没有提供BIG5/GBK转码及修改功能。

使用方法:
1. 将m_msg.s9解压缩,假设解压后为m_msg_dec.s9;
2.用applocale开ultraedit32打开m_msg_dec.s9进行修改;
3.将m_msg_dec.s9压缩,假设压缩后为m_msg_enc.s9;
4.备份原来的m_msg.s9,将m_msg_enc.s9重命名为m_msg.s9,修改生效。


附件: s9msg.rar (2005-4-14 23:52, 284.77 K)
该附件被下载次数 432
精华帖
顶部
性别:未知-离线 gameplore

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
好贴 1
功绩 7
帖子 274
编号 17912
注册 2004-9-18


发表于 2005-4-22 20:54 资料 短消息 看全部作者


QUOTE:
原帖由三国在飞于2005-04-15, 11:51:44发表
我试过,只能改对应的字(两个的改两个,三个的改三个)加多个都不行,会有乱码。

比如我们自制的剧本都要加些关之类的,如果把且兰加多个关字,进入游戏后很多字看不到且乱码。

可能是压缩的代码处理长度时有点问题,我现在没有san9游戏。

以前写那个程序就是为了该名字的,其他的没改过。可以修改一下压缩的代码
精华帖
顶部

正在浏览此帖的会员 - 共 2 人在线




当前时区 GMT+8, 现在时间是 2025-4-3 03:45
京ICP备2023018092号 轩辕春秋 2003-2023 www.xycq.org.cn

Powered by Discuz! 5.0.0 2001-2006 Comsenz Inc.
Processed in 0.024308 second(s), 10 queries , Gzip enabled

清除 Cookies - 联系我们 - 轩辕春秋 - Archiver - WAP