Archive for November, 2007

今日のみなみけ(南家餐桌)资源吸出和游戏系统研究

这是一个即没有H也没有恋爱的同人游戏(官方介绍), 里面的每一个角色都是攻略不能的, 主题上还是属于收集系的游戏, 游戏以假期的一个月为一轮, 通关后追加若干菜单, 可以不按预定菜色做饭, 当然要确保当天负责做饭的三姐妹之一不会把饭做糊掉.
以上介绍完毕, 直奔主题, 这个游戏我觉得比较厚道的因素, 就是语音了, 虽然不是全程的, 可是在非ecchi游戏中, 特别是同人, 有语音的可谓少之又少鸟.
基本上都是一些事件对话和日常对话, 例如早上遇到今天第一次见面的人, 她们会和玩家互相问候, 有慢悠悠的敦子的慢悠悠欧哈由, 也有知晓秘密的内田的yahoo, 当然也有男生的阿斯, 也有真希中气十足的早上好.
诶, 说起来令人印象深刻的还有那个脑袋被地铁加过的保坂怪哥哥的热情的歌曲, 令我想起了酒剑仙那首有语音的诗…
也不由得想起当时反编译仙剑3的剧情脚本, 试验发现可以给对话同时加上语音后的寂寞感…
让夏娜姐姐给龙葵妹妹配音应该会让龙葵娇羞有坚强的性格更加印象深刻吧~~
扯远了, 占位更新图像资源的压缩存储格式.
这款游戏的安装目录的image文件夹下有大量的fzl文件, 开OD跟踪, 发现程序会先试图在image目录搜索同名的*.png文件, 搜索不到时候, 就改为打开*.fzl文件.
于是就找了一个logo_0.fzl来分析, 拿压缩工具一压, 没有压缩率, 应该是加密或者压缩后的格式.
先看文件大小是24712, 也即#$6088, 然后在$8处看到了一个#$6048, 又在$40处看到数据的开始, 而前面是#$20个pending的00. 那么$8这里应该是存储压缩后数据的大小, 而文件头的大小是#$40. 观察前#$40字节, 没有发现#$40的数据, 所以文件头的大小应该是固定的.
根据经验, 存储压缩数据大小的前后很可能就是压缩前数据的大小, 以便申请适当的buffer, 那么$4处的01肯定不是, 而$C处的#$40000则非常可疑.
继续向下看, $10开始是$#20,1,#$100,#$100, 自然前面两个是长宽的可能没了, 而#$100*#$100 * sizeof(tagRGBA) = #$40000, 应该是一个256*256的图片, 压缩前的格式是4字节一像素的数据流.
因为前面要打开png文件, 所以怀疑这里跟png有什么关联, 用KANAL看了看, 主程序用到的算法有ADLER32, CRC32, ZLib deflate, 那前面2个都是hash算法没法用来作数据压缩, 看来应该只有zlib一种选择了, 为了防止程序用自己的压缩方式来压缩, 跟踪了logo_1.fzl的数据读取, $40处的数据是在第四次读取fzl文件时候取出的,

00564F5B  |.  6A 00                    PUSH 0                                   ; /pOverlapped = NULL
00564F5D  |.  50                       PUSH EAX                                 ; |pBytesRead
00564F5E  |.  8B03                     MOV EAX, DWORD PTR [EBX]                 ; |
00564F60  |.  FF75 10                  PUSH DWORD PTR [EBP+10]                  ; |BytesToRead
00564F63  |.  51                       PUSH ECX                                 ; |Buffer
00564F64  |.  FF3430                   PUSH DWORD PTR [EAX+ESI]                 ; |hFile
00564F67  |.  FF15 80405700            CALL NEAR DWORD PTR [<&KERNEL32.ReadFile>; \ReadFile

数据读出后, 在buffer处下内存访问断点, 断在一个三层循环处, 操作是读取

00545071  |. /E9 6B1E0000              |JMP 00546EE1
00545076  |> |837D EC 10               |/CMP DWORD PTR [EBP-14], 10
0054507A  |. |73 42                    ||JNB SHORT 005450BE
0054507C  |> |837D D4 00               ||/CMP DWORD PTR [EBP-2C], 0
00545080  |. |75 05                    |||JNZ SHORT 00545087
00545082  |. |E9 5F1E0000              |||JMP 00546EE6
00545087  |> |8B4D D4                  |||MOV ECX, DWORD PTR [EBP-2C]
0054508A  |. |83E9 01                  |||SUB ECX, 1
0054508D  |. |894D D4                  |||MOV DWORD PTR [EBP-2C], ECX
00545090  |. |8B55 C4                  |||MOV EDX, DWORD PTR [EBP-3C]
00545093  |. |33C0                     |||XOR EAX, EAX
00545095  |. |8A02                     |||MOV AL, BYTE PTR [EDX]

是一个结构漫长的函数, 向下翻动几页, 在同一个过程中发现invalid store blocks lengths和invalid code lengths set等信息, 那么这里可以确定读取fzl文件压缩数据的这段代码简直就是zlib的内层解压函数, 我就操出俺的zlibUI工具, 把logo_0.fzl的前面#$40字节减掉, 只留下#$40000, 拿去解了, 解出来的大小刚好是#$40000. 接下来, 不知道具体的原始数据的像素存储顺序前, 俺把解出来的文件名称改为logo_0.raw, 拿去xnview一看, 是混乱的重叠图像, kyouno三个字勉强可以看出十几个, 那么肯定不是RGBA了, 先不管这个, 接下来我就开始写XnView的插件, 用来查看fzl格式图片, 具体的像素排列就一边写一边分析了, 当然历经若干混乱的代码, 错位的, 黑白的, 有彩的, 色彩诡异的图像后, 终于完美解出了带透明的数据. 其中问题的解决还是无奈仔细手写了一个阵列然后手工排了一下可能的分布, 一举解出色彩诡异的形状正确图像后, 换了一下RGBA到BGRA就成功了.

这时候才忽然发现image目录下面除了fzl居然还有fzm文件, 给fzm文件增加解析花的时间比fzl更长, 虽然心里面大概有谱, 不过因为有谱导致的粗心, 写错鸟结构的长度, 发现bug后觉得这种依靠头脑清醒来保证代码正确不是办法, 就重新排查一遍加上重构了大部分硬性判断的代码, 改为载入文件时识别出像素和色深模式进行固定, 这下解析单行的代码看起来就工整了许多.

fzm呢, 基本上对等与8位的PNG, 所不同于大多PNG的是他在调色板使用了alpha透明, 对于alpha通道调色板的PNG, Fireworks支持, Iconworkshop支持, Xnview不透明, InfraView会进行合并.

继续补完这篇文章已经是一个月后的12月了, 不知为什么这个月过得格外的漫长, 或许是没有什么加班的缘故, 也或许是韬光养病的错觉, 感觉做了不少有意义和没意义的事情, 当然动画的minamike里也陆续出现了很多角色, 虽然原作中的角色还没有出全, 但是主要的几个配角, 例如成为这个游戏主线的女装版マコちゃん(眞子), 还有使得マコト无法正体复原的冬马, 当然还有令人呕心的保阪和同样具有幻想症状的アツコ(敦子), 说起アツコ呢还是觉得这个游戏里面的アツコ比较有漫画的风味, 或许是先入为主吧或许是声优表现出色, 感觉跟游戏里面的形象很切合, 软软的慢腾腾的傻傻的弱气娘啊. 而总是背着手笑的吉野的打招呼声音那是格外的清脆啊, 一看就是个好人, 可以入手大量的野菜种子, 果然是好人啊.


先写下要晚上要写的地方, 以免忘了

1. 乐呵呵的吉野的配音

2. NPC的有得没得的剧情

3. 梦幻合宿

4. 画面可动的诡异电视

5. 自己偷偷攒招待券的实久留店员

6. 家庭会议

7. 饭后甜点

8. 大叔C的厚道音乐