2005-4-15 11:51 三国在飞
[quote]原帖由[i]gameplore[/i]于2005-04-14, 23:52:21发表
[quote]原帖由[i]三国在飞[/i]于2005-04-05, 18:13:18发表
[quote]原帖由[i]gameplore[/i]于2005-04-05, 18:03:46发表
可以改的

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

至于输入,随便哪一个能输入BIG5码的输入法都可以 [/quote]
我做不出来的,不会解压啊,更不要说解压更改后再压缩回去!你能不能帮忙做个出来呢(修改器) [/quote]
原来是不会解压缩啊,其实前面的代码已经给出了。这里附上了一个简单的压缩/解压缩程序

我没有测试过,只在以前试过修改人名是可以的。完整的源代码也附上,想做完整的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,修改生效。 [/quote]
谢谢。转码的可以到别处。

我试过,只能改对应的字(两个的改两个,三个的改三个)加多个都不行,会有乱码。

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

2005-4-16 08:52 boylinming
我是新人,前两天才知道有这个论坛,看了LS的解压缩,不知道你们如何测试出来的,我觉得GetCode函数应该改进,昨晚测到0点30分,应该快了不少,方法是利用查表代替测试Bit位。(为了能够让大家看明白意思,我没有做进一步的优化)

m_bitPos初始化为0,不是7了。

struct CompressValue
{
        union
        {
                int nValue;
                BYTE byValue[4];
        };
};

int g_CodeLen[] =
{
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 0
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 1
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 2
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 3
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 4
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 5
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 6
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 7
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 8
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 9
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 10
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 11
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,  // 12
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,  // 13
        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,  // 14
        4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,  // 15
};

int g_nValue[] =
{
        0, 2, 6, 14, 30, 62, 126, 254
};

int g_nMask[] =
{
        1, 3, 7, 15, 31, 63, 127, 255, 511
};

unsigned int GetCode()
{
        // 得到3个字节的数据, 反序
        CompressValue data;
        data.byValue[3] = m_pSrc[m_srcPos];
        data.byValue[2] = m_pSrc[m_srcPos+1];
        data.byValue[1] = m_pSrc[m_srcPos+2];

        // 移位, 使得最高位是有效数据
        data.nValue <<= m_bitPos;

        // 查表得到有效数据里面Bit==1的个数
        int nSetBitsNum = g_CodeLen[data.byValue[3]];

        // 查表得到uCode1
        unsigned int uCode1 = g_nValue[nSetBitsNum];

        // 数据移位, 消去uCode1使用部分
        // 同时使得data.byValue[3]的Bit0就是uCode2的Bit0
        // x <<= y, 当 y < 0 时有问题, 如果直接用汇编写, 就可能不需要分之判断
        // (我的8086的汇编忘光了, 但一些DSP芯片支持这样的指令的)
        int nShiftNum = (2*(nSetBitsNum+1) - 8);
        if (nShiftNum > 0)
        {
                data.nValue <<= nShiftNum;
        }
        else
        {
                data.nValue >>= abs(nShiftNum);
        }
       
        // 通过掩码计算, 得到uCode2
        unsigned int uCode2 = (data.byValue[3] & g_nMask[nSetBitsNum+1]);

        // 计算bitPos和srcPos的改变, 并改变之
        m_srcPos += ((2*(nSetBitsNum+1)+m_bitPos) >> 3);
        m_bitPos += 2*(nSetBitsNum+1);
        m_bitPos &= 7;

        return uCode1 + uCode2;
}

2005-4-16 19:13 van
论坛里面的代码是直接反汇编得到的,所以只是和光荣的实际算法保持一致,而没有考虑效率的问题做进一步的优化。
欢迎提改进意见!

2005-4-16 20:19 van
你的算法有些问题
int nSetBitsNum = g_CodeLen[data.byValue[3]];
unsigned int uCode1 = g_nValue[nSetBitsNum];

在你的算法中nSetBitsNum可以等于8(data.byValue[3]=255),这时g_nValue就缓冲区溢出了。另外LS算法并没有限制在0~255之间,也可以是11111111110之类的

2005-4-18 12:36 boylinming
我开始领会错了,是会溢出。
我修改下,生成的曹操传data.e5文件和网上下载的一样。但里面有几个if语句很不爽,谁优化下,尽量不要清空计算机的流水线。修改后的程序连续的1的个数也不能太多,12个以后也可能会出问题(曹操传data文件里面包含了几部分,不知道是否也是这个原因)。那个大表格不用动,其它改动如下:
struct CompressValue
{
        union
        {
                unsigned int nValue;
                unsigned short sValue[2];
                BYTE byValue[4];
        };
};

int g_nValue[] =
{
        0, 2, 6, 14, 30, 62, 126, 254, 510, 1022, 2046, 4094, 8190, 16382
};

int g_nMask[] =
{
        1, 3, 7, 15, 31, 63, 127, 255, 511, 1023
};

unsigned int LSCompress::GetCode()
{
        // 得到4个字节的数据, 反序
        CompressValue data;
        data.byValue[3] = m_pSrc[m_srcPos];
        data.byValue[2] = m_pSrc[m_srcPos+1];
        data.byValue[1] = m_pSrc[m_srcPos+2];
        data.byValue[0] = m_pSrc[m_srcPos+3];

        data.nValue <<= m_bitPos;

        int nSetBitsNum = g_CodeLen[data.byValue[3]];
        int nSetBitsNum1 = g_CodeLen[data.byValue[2]];

        unsigned int uCode1;       
        unsigned int uCode2;

        if (nSetBitsNum >= 8)
        {
                uCode1 = g_nValue[nSetBitsNum+nSetBitsNum1];

                int nRealShiftNum = nSetBitsNum + nSetBitsNum1 + 1;
                data.nValue <<= nRealShiftNum;
                data.nValue >>= (16-nRealShiftNum);
                uCode2 = data.sValue[1];

                m_srcPos += ((2*nRealShiftNum+m_bitPos) >> 3);
                m_bitPos += 2*(nRealShiftNum);
                m_bitPos &= 7;
        }
        else
        {               
                uCode1 = g_nValue[nSetBitsNum];

                int nShiftNum = (2*(nSetBitsNum+1) - 8);
                if (nShiftNum > 0)
                {
                        data.nValue <<= nShiftNum;
                }
                else
                {
                        data.nValue >>= abs(nShiftNum);
                }
                uCode2 = (data.byValue[3] & g_nMask[nSetBitsNum+1]);

                m_srcPos += ((2*(nSetBitsNum+1)+m_bitPos) >> 3);
                m_bitPos += 2*(nSetBitsNum+1);
                m_bitPos &= 7;
        }       

        return uCode1 + uCode2;
}

2005-4-19 08:35 Maxwell
我考虑过表格的问题,不过后来测试了一下速度完全可以满足需要,因此保留了那种比较直观的算法。

2005-4-22 20:54 gameplore
[quote]原帖由[i]三国在飞[/i]于2005-04-15, 11:51:44发表
我试过,只能改对应的字(两个的改两个,三个的改三个)加多个都不行,会有乱码。

比如我们自制的剧本都要加些关之类的,如果把且兰加多个关字,进入游戏后很多字看不到且乱码。 [/quote]
可能是压缩的代码处理长度时有点问题,我现在没有san9游戏。

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

2005-4-22 22:31 三国在飞
[quote]原帖由[i]gameplore[/i]于2005-04-22, 20:54:21发表
[quote]原帖由[i]三国在飞[/i]于2005-04-15, 11:51:44发表
我试过,只能改对应的字(两个的改两个,三个的改三个)加多个都不行,会有乱码。

比如我们自制的剧本都要加些关之类的,如果把且兰加多个关字,进入游戏后很多字看不到且乱码。 [/quote]
可能是压缩的代码处理长度时有点问题,我现在没有san9游戏。

以前写那个程序就是为了该名字的,其他的没改过。可以修改一下压缩的代码 [/quote]
只是改名字,但不能乱改,比如曹操改成三个字的人名就不行(会出错),还有就是旗子也不对(还是原来的那个)

2005-6-5 16:11 elvis1000
有没有人会 C & Delphi的,可不可以把上面的C翻译成DELPHI,我只会DELPHI,实在看不懂!

boylinming写的好像和gameplore的不一样!

如果一次读取一个 integer (4 bytes),是不是前两个BYTE的值可以直接当作读取字典的值?还是应该要全换成二进位来分析呢?

2005-6-5 16:42 叶落秋寒
[quote]原帖由[i]elvis1000[/i]于2005-06-05, 16:11:37发表
有没有人会 C & Delphi的,可不可以把上面的C翻译成DELPHI,我只会DELPHI,实在看不懂!

boylinming写的好像和gameplore的不一样!

如果一次读取一个 integer (4 bytes),是不是前两个BYTE的值可以直接当作读取字典的值?还是应该要全换成二进位来分析呢? [/quote]
你先别看他们的代码
先把分解和还原原理看懂了(必须!)
再自已动手试着写写看。
LS文件的结构
0-15 文件头16个字节
16-271 字典256个字节
N组 12字节为一组控制信息(压缩后长度,原文长度,压缩数据起始地址)
数据段

2005-6-5 18:49 elvis1000
三十的240x240图片的压缩档(RGBquad+Bits)也有档头吗?还是直接把资料用lz11的原理压的?

2005-12-11 02:22 ALCLA
问一下,如何反汇编直接反汇编得到光荣的算法?而且压缩算法无论是LZ77,LZ78,LZW如果不确定具体如何操做,感觉很难解压,不知道如何得到准确的算法,我好象就不敢下手修改了,这个帖子不错,但是我想知道到底如何得到算法的?

2005-12-11 22:28 Maxwell
这个算法是van反汇编得到的。这个算法的可靠性是有保障的,不必非要搞清楚算法的名字,由于这个算法的一些特点,很难而且也不需要搞清楚压缩算法的细节。根据解压算法很容易构造一个压缩算法,即使这个算法跟光荣的算法不一致也能让解压算法正常工作。

2005-12-12 09:25 ALCLA
谢谢,van反汇编得到?我觉得算法的实现,和解开都不是难点,这个我都做过,字典在2的19还是多少次方以内都没什么问题,只是再大我电脑内存有问题不够,关键是我不知道van太守如何反汇编得到算法?恩,我去看看怎么反汇编,毕竟总不能老是=着人家把算法讲出来嘛

2007-9-25 18:12 神源拓也
虽然有点复杂,但还是能学习的 :^%

2008-8-27 11:22 隋唐英雄传
好东西:^%

页: 1 [2]
查看完整版本: ls11格式详解


Powered by Discuz! Archiver 5.0.0  © 2001-2006 Comsenz Inc.