注册 | 登陆
浏览模式: 标准 | 列表分类:游戏汉化

浅析PSP平台GIM图片文件中的DXT系列格式

众所周知,GIMPSP平台的一种标准图片格式,关于GIM格式,这次在这里就不多说了,要把它说清楚也是一项比较浩大的工程。基本上可以把GIM文件看作是一个图片集,可以存放各种形式的图形数据,包括色盘-索引图、真彩图以及下面要说的DXT

 

DXTS3 Graphics, Ltd.为了他们的Savage 3D加速卡开发的一系列有损图形压缩算法,最早叫做S3TC,包括DXT1, DXT2, DXT3, DXT4, DXT5,后来也统称为DXTn或者DXTC。随着被收录在微软的DirectX 6.0中,DXT逐渐被各软硬件厂商所采用。

 

下面分别简单讨论一下DXTn的算法:

 

DXT中,图片是被拆分成一个个4-pixel x 4-pixel的小块(英文称为texel)来看待的,当图片宽度或者高度不足4 pixels时,补足对齐之后再处理。在所有的DXTn中,每个4x4的块,都存放有两个16-bitARGB5650的颜色值(C0C1),以及4x42-bit的颜色索引。而在DXT2 – DXT5中,相对于DXT1,每个4x4的块还额外使用了64 bits来存放alpha信息。因此,DXT1中,每个4x4的块用8个字节来表示,而DXT2 - DXT5中,每个4x4的块用16个字节来表示。可以看出,在宽高固定的情况下,DXTn存储的图形数据大小也是固定的

 

可以看到,颜色索引使用了2 bits,可以表示4种颜色,因此还需要根据存放的2个颜色值插值出另外两个颜色。通用的公式如下:

C2 = 2 / 3 * C0 + 1 / 3 * C1

C3 = 1 / 3 * C0 + 2 / 3 * C1

公式1

但是,虽然DXT1没有额外保存alpha信息,它本身是支持1-bitalpha,这个支持是通过将C3固定为透明色来实现的。根据标准的S3TC算法,判断DXT1中某个块是否含有透明色,是通过比较C0C1来进行的。

C0 > C1时,表示没有透明色,C2C3根据前面的公式1进行插值算出。

C0 <= C1时,表示存在透明色,此时C3表示透明,C2的插值公式变为:

C2 = 1 / 2 * C0 + 1 / 2 * C1

公式2

要注意的是,这种判断标准并不是一个强制标准,听说有一些dxt压缩软件(nvidiadxt tool),为了获得更好的插值效果,是有可能会不按大小顺序来排列C0C1的,只有在压缩的时候让用户选择是否保存alpha,此时,只有压缩者自己知道是否存在alpha,而无论是微软的DDS还是PSP上的GIM,都不存在这样的标志来指明这个信息。。。orz 不过据我见过的GIM中的DXT1来说,都还是遵循前面的判断标准的。

 

下面再来说说DXT2DXT3DXT2DXT3的存储结构是一模一样的,唯一不同的地方是,DXT2中存储的颜色值是经过alpha预乘的(premultiplied),而DXT3的没有。以下以DXT3来进行讨论。

DXT3的色盘和索引部分与上面讲述的相同,而且因为DXT3中一定保存alpha信息,所以只需要用到公式1来做插值。DXT3相对DXT1,额外使用了64 bits来保存alpha信息,即一个4x44-bitalpha表,可以表示16级的透明度。每一个alpha分别对应该块中相应的像素点。

 

对于DXT4DXT5来说,情况和前面一样,DXT4DXT5唯一的不同之处也只在于DXT4的颜色值是经过alpha预乘的。下面以DXT5为例。

 

DXT5DXT3一样,也额外使用了64 bits来存储alpha信息,但是存储的结构确不尽相同。DXT5中,存放有两个8-bitalpha(a0a1)4x43-bitalpha索引。同前面一样,因为3 bits可以索引8alpha值,因此需要插值出另外6alpha。而这里的插值算法,也分为两种:

a0 > a1:

a2 = 6 / 7 * a0 + 1 / 7 * a1

a3 = 5 / 7 * a0 + 2 / 7 * a1

a4 = 4 / 7 * a0 + 3 / 7 * a1

a5 = 3 / 7 * a0 + 4 / 7 * a1

a6 = 2 / 7 * a0 + 5 / 7 * a1

a7 = 1 / 7 * a0 + 6 / 7 * a1

a0 <= a1时:    

a2 = 4 / 5 * a0 + 1 / 5 * a1

a3 = 3 / 5 * a0 + 2 / 5 * a1

a4 = 2 / 5 * a0 + 3 / 5 * a1

a5 = 1 / 5 * a0 + 4 / 5 * a1

a6 = 0

a7 = 255

 

实际应用中,DXT1DXT3DXT5使用较多,DXT2DXT4甚少被使用。而在PSPGIM中,只存在DXT1DXT3DXT5(类型编码分别是8, 9, 10),不支持DXT2DXT4P.S. GIM中还支持三种所谓的DXT1ExtDXT3ExtDXT5Ext的格式(类型编码分别是264, 265, 266),因为没有找到相关资料,所以在这里就不进行讨论了

 

下面举几个例子来看看GIM中的DXT1DXT3(DXT5GIM还没见过,不过应该和DXT3差别不大,alpha存储结构不一样罢了)

 

DXT1

 

来看这样一组数据:56 7E 78 F8 A2 99 A0 60    3F BF B7 95 41 71 60 58

这是从某个GIM中提取出来的DXT数据,因为是DXT1,所以这里其实是两个4x4块的数据,下面以前面的一个块来分析。

a.56 7E 78 F8    b.A2 99    c.A0 60

数据包括三个部分,其中,a是颜色索引,2 bits一个像素,共4x4个像素;bc是两个颜色值,即C0C1

 

索引部分,其二进制数据,2 bits为一组,如下:

01 01 01 10 01 11 11 10 01 11 10 00 11 11 10 00

根据以上数据可以得到该图块各像素的颜色索引信息,如下:

01

01

01

10

01

11

11

10

01

11

10

00

11

11

10

00

颜色值部分,C0C1分别为0x99A20x60A0,其二进制数据,16 bits一组,按ARGB5650划分为:

C010011 001101 00010

C101100 000101 00000

C0RGB分别为19132,映射到256色系里分别是1565316

C1RGB分别为1250,映射到256色系里分别是99200

因为此处C0 > C1,因此使用256色系里的C0C1利用公式1分别对RGB三色进行插值,可得到:

C2RGB分别为(256色系) 1374211

C3RGB分别为(256色系) 118315

色盘如下:

00

01

10

11

通过索色,便可得到图块的最终显示结果:

01

01

01

10

01

11

11

10

01

11

10

00

11

11

10

00

 

DXT3

 

来看这样一组数据:55 55 55 55 E0 FF DF FF    70 29 60 EF 00 FC 00 F7

这是从某个GIM中提取出来的DXT数据,因为是DXT3,所以这里是一个4x4块的数据。

 

前面8个字节55 55 55 55 E0 FF DF FF,与前面描述的DXT1的格式是一样的,此处就不再重复说明了。最终的显示结果为:

01

01

01

01

01

01

01

01

01

01

01

01

01

01

01

01

其实,这个GIM文件中的DXT数据,每个4x4的块,前8个字节都是一样的,那么难道整幅图就是一片单色吗?当然不是,别忘了还有后面8个字节存储着alpha信息呢,对,这幅图完全是依靠alpha来进行显示的,必须混合alpha,然后配合背景色才能看到最终的效果。

 

alpha信息是4x44-bit数据,得到图块的alpha信息:

7

0

2

9

6

0

14

15

0

0

15

12

0

0

15

7

因为是4-bit16alpha,所以要在真彩环境中显示的话,还要映射为256级的值,然后带入到图块中和前景色、背景色做混合就能看到最终结果了,此处过程省略,直接给出背景色为黑色时的最终结果(近似)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

后记:在这个GimConv横行的年代,再去研究有关gim的东西有没有意义,我在这里不想讨论。但是,多了解一种格式,多了解一种结构,总是不会有坏处的。 by Xinyu


转载请注明作者和出处,谢谢!

Tags: 汉化, gim, psp, dxt, 游戏

PSP《大众高尔夫2P》XB资源包结构破解分析

此游戏资源绝大部分都在PSP_GAME\USRDIR\xbdata目录下,全部是以.xb为后缀的一种打包文件格式,现对此格式分析如下:

这种文件一共分为四大部分:

1。文件头(File_Header)
2。文件信息(File_Info)表
3。文件名表,带一个压缩头(Compress_Header)
4。文件数据,如为压缩文件,则还有一个压缩头(Compress_Header)

下面进行具体解说:

1。文件头(File_Header)

C++代码
  1. struct File_Header   
  2. {   
  3.     unsigned int signature; // 签名标识, 固定为0x01006578   
  4.     unsigned int number_of_file; // 子文件个数   
  5. };  

 

2。文件信息(File_Info)表

紧接着文件头的,就是一个文件信息表,有多少个文件,表里就有多少个文件信息结构。该结构定义如下:

C++代码
  1. struct File_Info   
  2. {   
  3.     unsigned int file_size_org; // 源文件大小   
  4.   
  5.     unsigned int file_pos :24; // 文件起始位置,= offset / 4   
  6.     unsigned int compress_type :8 // 压缩类型,4种已知   
  7. };  

此结构一共2个DWORD值。
第一个DWORD值为原始文件的大小,注意在某些压缩类型里,这个值不一定等于压缩头中的解压数据大小,可能是还有一层压缩或者别的什么,因为目前并没有解压缩,不能确定;
第二个DWORD值的低3个字节,为文件的起始位置,注意这里不是偏移地址,偏移地址需要用这个值再乘以4,即file_offset = file_pos * 4;
第二个DWORD值的最高1个字节,表示文件的压缩类型,目前已知的如下:
0x00 - 未知压缩算法,在压缩头和压缩数据之间,存在一个类似字典的数据块,并且不计入压缩数据大小;
0x10 - 未知压缩算法,类似或等同于0x00,不能确定;
0x20 - lzss压缩或者相关变种,这种压缩破起来倒是很容易;
0x30 - 未压缩,无压缩头,直接就是raw数据。

3。文件名表

此部分带一个压缩头,然后接数据。压缩头定义如下(通用): 

C++代码
  1. struct Compress_Header   
  2. {   
  3.     unsigned int size_decompressed; // 解压数据大小   
  4.     unsigned int size_compressed; // 压缩数据大小(包括此结构)   
  5. };  


此处,如果size_compressed为0,代表未压缩;不为0代表经过压缩,算法是lzss或者相关变种。

4。文件数据

如果compress_type为0x30,则为raw数据,无压缩头;其他情况皆有一个压缩头。

从资源处理的角度来说,此整合包的分解和重组程序是非常好写的,最关键的地方在于对0x00和0x10这两种压缩算法的破解。

前不久已经有人把上述两种未知压缩破解了,分别为Huffman+Lzss和单独的Huffman,具体的细节和分析可以参考这篇文章http://blog.csdn.net/jerryutscn/archive/2010/08/01/5780655.aspx by Xinyu on 2010.08.19

Tags: psp, 大众高尔夫, 破解, 汉化

DASM破解游戏资源入门级简易教程

众所周知,很多游戏的图片文本影音等资源,都是经过打包、加密或者压缩的,那么为了获取这些资源,只能对算法进行分析,写出相应的破解程序,从而达到资源提取的目的。

但目前来说,使用公开的已知算法来加密或压缩的游戏,毕竟是少数,大多游戏厂商都会对已知算法进行一定的修改或者干脆自己发明一种算法,这时想要破解就没那么容易了。还好为了速度上的考量,这样的算法一般都不会很复杂,我们还是可以通过对程序进行dasm来进行分析破解。

昨天受朋友之托,让帮忙破解pc版ys2的文本文件"libre.ys2",花了10来分钟搞定,虽然无论从分析还是算法的角度来说,都属于非常简单的级别,但是对于从未接触过dasm破解的朋友来说,却无疑是一个很好的试刀例子。本文通过描述此次的破解过程,讲述了dasm破解游戏资源的一般思路,希望能达到抛砖引玉的效果。

» 阅读全文

Tags: 破解, 汉化, ys2, asm, ida

MHP2G汉化补丁v2.0(CG汉化组)

08年5月5日 00:30 更新v2.0汉化补丁

汉化人员表:

策划:Bill_22


程序:ZXP moonsun1234(天马)  Crainy(鲁迅)  XINYU serige

补丁制作:XINYU

翻译:SHIN真红 FoxUU  CHENGANDPENG(咸蛋) Phoenixガイ エロせんにん
candy123(盘子)  一击离脱 煬 谁 傀儡回し 真007XRB cumar

润色:冥夜の羽翼 Springlie(幸福花园)  隐形超人 Ashura
美工:Meissen

CG测试组:蘑菇 Falcom  期待的轨迹  隐形超人 游龙

战队测试名单:

Zero战队
Zero.Roy  Zero.killuer  Zero.OoLaLa   Zero.小能  Zero.番薯

Gray战队
Gray.天堂牙 Gray.花花 Gray.凉宫虚 Gray.夜羽 Gray.胭脂恨 Gray.真007XRB


SS战队
SS.Dengyu  SS.LEON  SS.天使 SS.天然 SS.绯色之红 SS.小雅 SS.树树 SS.发发
      SS.鬼舞姬 SS.色拉 SS.飘飘

此游戏为CG汉化组独立汉化,所有汉化内容(包含原怪物猎人2P汉化):本文 图片等,为CG汉化组所有,未经最终授权不得擅自更改与使用,如果不喜欢我们的汉化,那请无视便好,我们不接受一切攻击性言论,转载时请注明出处。汉化中出现的问题和错误还请见谅,也请即时向我们反映。汉化补丁最终解释权归<http://www.cngba.com/>所有,谢谢合作。

CG原发布帖:http://www.cngba.com/thread-17383819-1-1.html 

启用MEDIA INSTALL(媒体安装)功能的玩家请打完补丁后,重新进行MEDIA INSTALL,并且开启此功能,否则部分文本仍为日文

by Xinyu:关于打过汉化补丁后,MEDIA INSTALL(媒体安装)会提示损坏并自动关闭的问题,这是各汉化版的一个通病,估计是游戏对安装到记忆棒上的内容有校验机制,目前此问题还无法解决!!

点此下载汉化补丁v2.0(内含正常及YY猫名两个版本,对应任意大小ISO)

Tags: mhp, 2g, 汉化, 补丁, cg

PSP“星之海洋-初次启程"破解研究 之 初步分析

2007年12月30日 10:40 更新

解压以后一个800M+的bin文件,除了PMF动画,游戏中所有的资源都打包在里面。

用WinHex打开以后一看过去就知道是个很简单的包,文件头+指针表+数据的格式,直接上伪代码:

Bin文件头

C++代码
  1. struct BinHeader   
  2. {   
  3.     DWORD file_count; // 打包文件数量   
  4.     DWORD file_pointer_offset; // 文件指针表偏移   
  5.     DWORD file_offset_0; // 某特殊文件起始偏移   
  6.     DWORD file_offset_1; // 真正打包文件起始偏移   
  7. }  

文件指针表结构更简单,每个文件就用一个DWORD来表示该文件的起始偏移。按照0x800字节对齐。

大概往下看了一下,打包的文件中应该有好几种类型,但基本上可以确定文本、图片之类的资源一定是被压缩在那些"SLZ”文件中。此类文件容易识别,因为文件头中有签名标识。

SLZ文件头

C++代码
  1. struct SLZHeader                         
  2. {                         
  3.     DWORD signature; // 签名,一定是0x0?5A4C53,即"SLZ "   
  4.     DWORD size_compr; // 压缩数据大小,不包括此文件头   
  5.     DWORD size_decompr; // 解压后数据大小,即实际大小   
  6.     DWORD next_offset; // 下个连续SLZ文件相对此文件头起始地址的偏移   
  7. }  

大略浏览了一下,此类文件应该是此游戏唯一一种压缩格式的文件,所以只要把这个解了,应该就能获得全部资源了。

SLZ压缩文件,顾名思义,是采用的LZ系列压缩算法(SLZ难道表示Super LZ -_-||),压缩结构使用标准LZSS格式,每段数据第一个字节的8位用来表示接下来的8组数据的形式,0表示压缩数据,1表示未压缩数据。

但请注意到签名中的最高位有0x01和0x02两种取值,目前此数据作用未知!

据我观察,当next_offset不为0时,说明此SLZ文件后紧跟着另一个SLZ文件,而当两个压缩文件之间不是字节连续而是存在一定字节的空隙时(即"next_offset>size_compr+sizeof(SLZHeader)"时),这些空隙中是有合法(但不确定有用)数据的!所以我推测有可能是这些SLZ文件解压后和空隙间的数据连接起来是一个文件。有待验证。

基本上小花了点时间就可以分析到这种程度了,再接下去才是最难的部分。以后有时间可能再研究看看了,说不定已经有高人研究出来了呢。本文仅是起一个抛砖引玉的作用,虽然东西不多,不过对于有志学习破解的朋友应该还是有一定参考价值的。

待解决的关键问题:

前面说了,一个字节表示接下来8组数据是压缩还是未压缩,现在的关键就是如果是压缩的,那么它的格式是怎样的,一共占几个字节,哪些位是表示什么数据,把这些弄清楚了,解压也就不成问题。

还有一点,这个bin文件的大文件包之中,还有很多小文件包,即大包中并不是每个文件都是单独的SLZ文件,它有可能又是一个文件包,里面包含数个SLZ文件,而这种小文件包似乎拥有和大文件包不同的文件头结构,我没有深究,不过看上去也不是很复杂就对了,稍加分析应该就能弄明白。

最后,其实使用LZ系列压缩算法对于我们来说有一个好处,就是即使它是开发者自己改编的LZ变种,而我们又无法还原压缩程序,那么最坏的情况也就是修改完资源后,按照LZ的结构格式把资源进行不压缩打包,即俗称的“伪压缩”,虽然会使最终的ISO比原始的大不少,但至少还可以期待CSO帮忙做点压缩的工作。

Tags: 星海, 汉化, 破解, lz