樱花大战SPR文件格式不完全分析

看到SPR后缀很容易想到sprite这个词,但分析之后才发现樱花大战的SPR文件并不是一个简单的精灵文件,倒是更像一个小型的打包格式,将跟同一sprite有关的图像啊,对齐信息啊等等都打包在一起了。鉴于SPR内容的多样性,本文仅介绍文件的整体结构以及图像部分。(http://blog.csdn.net/leexuany)

写这篇文章完全出于个人兴趣所致,至于提取工具就不发布了,van的RPGViewer2.8就可以提取樱花大战SPR的图像部分。

前16字节为文件标识 "SEGA SPRED 02.0M"
然后是N个文件索引(N一般是15,存在空的索引,数据为Big-endian)
struct spr_index {
  unsigned int offset;  // 子文件偏移地址
  unsigned int size;    // 子文件大小
  unsigned int type;    // 子文件类型代号(图像的代号是2)
  unsigned int reserve; // 总是零
};
最后是根据索引分布的子文件数据。

举个例子,游戏中的鼠标指针(SAKURA1/SYSTEM/ICON/POINT.SPR)的内容:

Offset | 0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F|
--------+------------------------------------------------+----------------
00000000|53 45 47 41 20 53 50 52  45 44 20 30 32 2E 30 4D|SEGA SPRED 02.0M
00000010|00 00 01 00 00 00 10 10  00 00 00 01 00 00 00 00|................
00000020|00 00 11 10 00 00 19 BA  00 00 00 02 00 00 00 00|................

其中第2条索引的含义就是,文件从$00001110开始,大小为$000019BA字节,类型代号为2,也就是图像数据。

SPR图像数据前10字节是图片头部,结构如下

struct spr_pic_info {
  unsigned short pic_count; // 图片的总个数(Big-endian)
  unsigned short var2;      // 作用不明,好像总是1
  unsigned short var3;      // 作用不明,好像总是1
  unsigned short var4;      // 作用不明,好像总是0
  unsigned int var5;        // 作用不明,好像总是0
  unsigned int var6;        // 作用不明,好像总是0
};

然后pic_count个子图片信息索引

struct spr_subpic_info {
  // 全部是Big-endian,不另作说明
  unsigned short width;
  unsigned short height;
  unsigned short var2;
  unsigned short var3;
  unsigned int offset;  // 子图片的偏移地址,从这些索引结束后开始计算。
  unsigned int size;
};

图片的实际数据是压缩过的,解压缩后的数据为16位的1555格式。这里简单介绍一下压缩算法。

取第一字节,一字节含8个二进制位,可取0或1两种值。
1表示对应1字节未压缩的数据,直接复制即可;
0表示对应一个压缩过的数据串,从数据源中取2字节,假设为 YZ XU,那么就从临时缓冲中的XYZ处复制(U+3)字节。
然后依次类推。。。具体请参考解压代码。

void spr_decompress(char *SrcBuf, int SrcSize, char *DestBuf, int DestSize) { char *TmpBuf = new char [0x1000]; memset(TmpBuf, 0, 0x1000); int TmpPosIn = 0x0FEE, TmpPosOut; unsigned char flag; int flag_count = 0; int SrcPos = 0; int DestPos = 0; int LoopCount; while (1) { if (SrcPos >= SrcSize) break; if (DestPos >= DestSize) break; if (flag_count == 0) { flag = SrcBuf[SrcPos++]; flag_count = 8; } if (flag & 0x01) { // 1 未压缩的数据 flag >>= 1; flag_count--; DestBuf[DestPos] = SrcBuf[SrcPos++]; TmpBuf[TmpPosIn] = DestBuf[DestPos++]; TmpPosIn = (TmpPosIn + 1) % 0x1000; } else { // 0 重复的数据 flag >>= 1; flag_count--; LoopCount = (SrcBuf[SrcPos+1] & 0x0F) + 3; TmpPosOut = SrcBuf[SrcPos+1]; TmpPosOut = ((TmpPosOut << 4) & 0x00000F00) | (SrcBuf[SrcPos] & 0xFF); SrcPos += 2; while (LoopCount > 0) { DestBuf[DestPos] = TmpBuf[TmpPosOut]; TmpBuf[TmpPosIn] = DestBuf[DestPos++]; TmpPosIn = (TmpPosIn + 1) % 0x1000; TmpPosOut = (TmpPosOut + 1) % 0x1000; LoopCount--; if (DestPos >= DestSize) break; } } } delete TmpBuf; }

樱花大战资源分析之二 SPR文件格式不完全分析相关推荐

  1. 小学计算机学情分析报告,二年级学生学情分析报告

    与<二年级学生学情分析报告>相关的范文 活动意义 1.让学生在生活中体验应用数学的快乐: 2.让学生在生活中感受数学知识的作用: 3.让学生在生活中善于用数学表达心情: 4.让学生在生活中 ...

  2. 计算机网络实验以太网帧分析,实验二 用Ethereal捕获并分析以太网帧格式

    <计算机网络>实验报告 – 实验二 指导老师:李旭宏 ------------------------------------------------------------------- ...

  3. SpringBoot2.0源码分析(二):整合ActiveMQ分析

    SpringBoot具体整合ActiveMQ可参考:SpringBoot2.0应用(二):SpringBoot2.0整合ActiveMQ ActiveMQ自动注入 当项目中存在javax.jms.Me ...

  4. 小米的抢购骗局+小米的抢购页面的源代码分析(二)文本数组的分析

    首先小米源代码的一部分是一个非常非常大的字符串数组,分析它非常耗费时间,但是要搞明白必须去做.. var _$ = [ //数组0位置,是空. "", //2位置,是抢购的开始日期 ...

  5. React源码分析(二)= Reac初次渲染分析

    文章目录 1. render阶段 legacyRenderSubtreeIntoContainer 1.1. legacyCreateRootFromDOMContainer 1.1.1. React ...

  6. Android7.0 Phone应用源码分析(二) phone来电流程分析

    当有来电通知时,首先接收到消息的是Modem层,然后Medoem再上传给RIL层,RIL进程通过sokcet将消息发送给RILJ(framework层的RIL),同样进入RILJ的processRes ...

  7. 死磕 java集合之TreeMap源码分析(二)- 内含红黑树分析全过程

    2019独角兽企业重金招聘Python工程师标准>>> 欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 插入元素 插入元素, ...

  8. bytebuddy实现原理分析 源码分析 (二)

    bytebuddy实现原理分析 &源码分析 四.字节码的操作(implementation ) pkg 4.1 bytecode :pkg 4.1.1 StackManipulation :c ...

  9. 空间分析(二)——统计进阶

    空间分析(二)--统计进阶 格局分析 Join count统计 Lacunarity analysis Centrography 点模式分析 密度分析 方位分析 中心位置 标准差椭圆 属性分析 其它 ...

  10. Licode入门学习:MediaStream源码分析(二)

    Licode服务与启动过程分析 MediaStream源码分析(一) MediaStream源码分析(二) MediaStream源码分析(三) WebRtcConnection源码分析(一) Web ...

最新文章

  1. Ubuntu16.04安装NVIDA显卡驱动
  2. Python学习笔记:进程和线程(起)
  3. 2013年1月18日调试触发器“表发生了变化,触发器或函数不能读它”的出现原因,以及解决方案...
  4. 好家伙,MacOS 新版本终于删掉自带 Python2,连 Python 死忠粉都叫好!
  5. js屏蔽浏览器(IE和FireFox)的刷新和右键等功能
  6. pycharm 中HTML代码的对齐
  7. bat 复制文件夹_新建366个文件夹,你用了2小时,我使用excel与bat命令1分钟搞定...
  8. 普林斯顿微积分读本篇十三:积分
  9. JAVA idea中安装P3C方法和使用指南
  10. unix环境中以下列出的oracle,浙江中医药大学2012研究生计算机复习题
  11. 构造和析构:construct,destory
  12. Office 365 IT Professional—— 如何将Office 365中的文档同步到客户端,加强协同管理
  13. HEVC(H.265) 基础知识
  14. MySQL 的read_only super_read_only
  15. html 抽奖的页面,html网页抽奖
  16. 做一个程序媛是一种什么体验?
  17. ZJ-神经网络训练时间长的原因
  18. python数据类型对应布尔值_Python基础数据类型之整型,布尔值,字符串
  19. 【日常篇】005_用Python制作《太空大战》
  20. 参数反演 计算机,滑坡体土体的力学参数反演方法、装置及计算机设备与流程...

热门文章

  1. HP 打印机驱动安装报错Return code: 1603解决办法
  2. 其他计算机才能打印,关于HPM126A打印机共享问题-共享之后主机得打印一次后其他电脑才能打印...
  3. window.crypto.subtle进行rsa-oaep加密
  4. CoVaR计算手册-动态CoVaR模型-数据、代码、步骤
  5. ssh远程连接windows
  6. 常见linux软件下载地址
  7. Ilasm And Ildasm Practice
  8. WinRAR 激活的小办法
  9. Ajax技术体系的组成部分
  10. 李雅普诺夫指数的计算