.osr 文件格式解析(五) - 回放数据ReplayData
2016-05-16 18:50
381 查看
按照ppy的描述,ReplayData是经过Lzma压缩后的数据,压缩前也是一串逗号分隔的字符串。
LZMA是7-Zip程序中7z格式的默认压缩算法。LZMA能提供给用户极高的压缩比及较快的压缩速度,它非常适合与应用程序集成。
压缩速度在双核处理器上可以达到 2 MB/秒。
解压缩速度在英特尔酷睿2 或 AMD 速龙 64 上可以达到 20-30 MB/秒。
较小的解压缩内存需求:8-32 KB(依赖于字典大小)
较小的解压缩代码:2-8 KB
LZMA 解码器仅使用整数运算,可以在任何主流的 32 位处理器(或在一定条件下的 16 或处理器)下运行。
LzmaLib编译
解压SDK后,在C\Util\LzmaLib下可以找到LzmaLib.dsw工程,VC6可以编译通过,生成LZMA.lib和LZMA.dll(如果没改输出路径,dll可能在C盘根目录)。然后把LzmaLib.h、Types.h、LZMA.lib和LZMA.dll复制到自己工程的根目录,准备工作就可以说是完成了。
LZMA的使用
LZMA就2个函数,一个用于压缩,一个用于解压:
MY_STDAPI LzmaCompress(…);
MY_STDAPI LzmaUncompress(…);
在要使用lzma的地方,加上如下代码,就可以了
LzmaCompress
压缩完毕后,dest里的就是压缩后的数据,destLen则是压缩后的长度,props里记录了压缩时所选的参数。
Lzma数据的保存
通常用以下结构来将压缩后结构保存到文件:
经LzmaCompress压缩后,props、srcLen和dest,这三样数据都是需要保留的,在解压时要依靠着三部分的数据来完成解压。LzmaLength则是三部分数据加起来的长度。
LzmaUncompress
解压后dest里即是原本的数据。
其中:
- LzmaData.lzmaLength对应int ReplayDataLength
- LzmaData.props对应ReplayData[0-4]字节
- LzmaData.srcLen对应ReplayData[5-12]字节
- LzmaData.dest 对应ReplayData[13]以后剩下字节
(其实,如果内存对齐是1的话,可以对整块数据进行内存拷贝的)
所有使用和osrLifeBar一样的方式用split进行分割就好了,这里就不再赘述了。
osrReplayData定义如下:
LZMA
LZMA简介
以下摘自7-Zip官网:LZMA是7-Zip程序中7z格式的默认压缩算法。LZMA能提供给用户极高的压缩比及较快的压缩速度,它非常适合与应用程序集成。
压缩速度在双核处理器上可以达到 2 MB/秒。
解压缩速度在英特尔酷睿2 或 AMD 速龙 64 上可以达到 20-30 MB/秒。
较小的解压缩内存需求:8-32 KB(依赖于字典大小)
较小的解压缩代码:2-8 KB
LZMA 解码器仅使用整数运算,可以在任何主流的 32 位处理器(或在一定条件下的 16 或处理器)下运行。
LZMA SDK
SDK下载:LZMA SDKLzmaLib编译
解压SDK后,在C\Util\LzmaLib下可以找到LzmaLib.dsw工程,VC6可以编译通过,生成LZMA.lib和LZMA.dll(如果没改输出路径,dll可能在C盘根目录)。然后把LzmaLib.h、Types.h、LZMA.lib和LZMA.dll复制到自己工程的根目录,准备工作就可以说是完成了。
LZMA的使用
LZMA就2个函数,一个用于压缩,一个用于解压:
MY_STDAPI LzmaCompress(…);
MY_STDAPI LzmaUncompress(…);
在要使用lzma的地方,加上如下代码,就可以了
#include "LzmaLib.h" #pragma comment(lib,"LZMA.lib")
LzmaCompress
std::string str="aaabbbcccdddeee"; //假定要压缩的字符串 byte *src = (byte*)str.c_str(); //原始数据的字节数组 size_t srcLen = str.length(); //原始数据的长度 size_t destLen = str.length(); //输出数据的长度 byte *dest = new byte[destLen]; //储存压缩结果的数组 byte props[5] = { 0 }; //5字节props数据 size_t propsSize = LZMA_PROPS_SIZE; //props的长度,LZMA_PROPS_SIZE=5 ZeroMemory(dest, destLen); //LzmaCompress压缩 //LzmaCompress 有很多压缩参数,使用默认值则填-1,具体的参数说明见LzmaLib.h int res = LzmaCompress(dest, &destLen, src, srcLen, props, &propsSize, -1, 1 << 24 ,- 1, -1, -1, -1, -1); ////res返回值校验,返回0则表示压缩成功 //switch (res) //{ //case SZ_OK: //0 - OK //case SZ_ERROR_DATA: //1 - Data error a566 //case SZ_ERROR_MEM: //2 - Memory allocation arror //case SZ_ERROR_UNSUPPORTED: //4 - Unsupported properties //case SZ_ERROR_INPUT_EOF: //6 - it needs more bytes in input buffer(src) // break; //}
压缩完毕后,dest里的就是压缩后的数据,destLen则是压缩后的长度,props里记录了压缩时所选的参数。
Lzma数据的保存
通常用以下结构来将压缩后结构保存到文件:
struct LzmaData{ int lzmaLength; byte props[5]; __int64 srcLen; byte *dest; }
经LzmaCompress压缩后,props、srcLen和dest,这三样数据都是需要保留的,在解压时要依靠着三部分的数据来完成解压。LzmaLength则是三部分数据加起来的长度。
LzmaUncompress
LzmaData lzmaData; //假如已经从文件中读取了要解压的数据 byte *src = (byte*)data.dest; //获取要解压的数据的字节数组 size_t srcLen = data.lzmaLength-13; //解压数据的长度(总数据长度减去props和srcLen的长得,即减13) size_t destLen = data.srcLen; //压缩文件原来的长度(解压后的大小) byte *dest = new byte[destLen]; //用来保存解压后的数据 byte *props = data.props; //5字节props数据 size_t propsSize = LZMA_PROPS_SIZE; //props的长度,LZMA_PROPS_SIZE=5 ZeroMemory(dest, destLen); int res = LzmaUncompress(dest, &destLen, src, &srcLen, props, propsSize);
解压后dest里即是原本的数据。
ReplayData
运用Lzma算法我们就可以把第三章取出来的int ReplayDataLength和byte *ReplayData还原成原来的数据了。其中:
- LzmaData.lzmaLength对应int ReplayDataLength
- LzmaData.props对应ReplayData[0-4]字节
- LzmaData.srcLen对应ReplayData[5-12]字节
- LzmaData.dest 对应ReplayData[13]以后剩下字节
(其实,如果内存对齐是1的话,可以对整块数据进行内存拷贝的)
真正的回放数据————osrReplayData
我们从ReplayData中得到了dest,这也是个文本,形如 w | x | y | z这样的以逗号分隔的数据。所有使用和osrLifeBar一样的方式用split进行分割就好了,这里就不再赘述了。
osrReplayData定义如下:
struct osrReplayData { __int64 delay; //距离上个动作的时间(毫秒) float X; //鼠标的X坐标(从0到512) float Y; //鼠标的Y坐标(从0到384) int key; //鼠标、键盘按键的组合 (M1 = 1, M2 = 2, K1 = 5, K2 = 10) };
相关文章推荐
- 为什么需要学习C语言
- 使用Mob工具实现QQ、微信、新浪微博登录
- Linux dirname、basename 指令
- Linux xargs将输出数据流转换成命令参数
- Sudoku
- eventsource 服务器发送事件
- Android学习——Dialog
- VMware卸载出现“the msi failed”解决办法
- cglib 动态代理
- CSS选择器
- [背包]
- 前端 要了解是的事情
- AndroidStudio目录结构视图解说,androidstudio视图
- 软件工程个人作业07
- bean注入
- ListView item点击事件问题:第一次点击有效,再次点击item无效。场景是在item的展开效果
- 51nod 1040 1060 (数论)
- 跟我详读ndk(第二篇)
- Android屏幕适配方案(个人觉得不错,比percent-support-lib好用)
- setContentView()与LayoutInflater.from()的区别-android