diff --git a/docs/archive/bluekiller.htm b/docs/archive/bluekiller.htm new file mode 100644 index 0000000..b38979c --- /dev/null +++ b/docs/archive/bluekiller.htm @@ -0,0 +1,22 @@ + +

游戏汉化教学贴

更新至[第五篇 GIM图像的破解 第二篇 进阶篇]-bluekiller

文本的导入导出基础篇

文本的导入和导出基础篇

作为游戏文本导出的最基本的工具,我们可以使用网上享有盛名的WQSG v1.0.2007.03110版和 CrystalScript文本导入和导出工具。(以后简称WQ和CS)

当然这2个工具未必能覆盖所有的PSP游戏的文本导入和导出,本章介绍的是一个汉化的流程或者说是基本的方法,大家在熟悉方法后,可以自己写一些程序提高导入导出的效率。汉化是一件需要耐心、毅 力、时间、技术、合作的工作,当你想汉化一个游戏的时候,你要做好充分的准备。

案例:圣女贞德(日版)

解包圣女贞德日版的ISO。剧情文本在 PSP_GAME\USRDIR\DATA\EVENT

文本的导出

image

步骤1 启动WQ。


步骤2 rom按钮处加载需要导出文本的文件,我们以圣女的剧情文本ST1020AB.BIN文件为例子。码表就是游戏的文本编码,当然在这里我可以告诉你圣女贞德的码表是SJIS。每个游戏的文本编码不一定是 SJIS,也可能是unicode编码,也有可能是unicode编码的扩展UTF-8编码,扯远了,基于后两种编码的导出,这里不作介绍,留给进阶者自己思考把。

步骤3 好,码表选择后的下一步就是选择控制符码表,控制符的目的就是游戏文本导出后的每行文本显示的上下句连接是否采用回车等,方便以后翻译汉化的语句调整,加了控制符,一般的翻译都能胜任,没有控制符,文本也能导出,但是会出现上下句文本语序的倒置,因为大家都知道日文和中文的语序不一样的。至于控制符,也属于进阶范围,需要有一定的程序基础,每个游戏的控制符不一,需要灵活应用,这里也就不再介绍。

步骤 4 在开始的16进制地址填写0。

步骤 5 在结束的16进制地址用取段最大按钮,获得ST1020AB.BIN的字节数,也就是说ST1020AB.BIN的容量。

步骤 6 字节过滤填入2,一般日文SJIS都是双字节,所以一个日文字符是占用2个字节,我们设置为小于等于2,小于2的文字不导出。

步骤 7 开始导出,替导出的文本取名ST1020AB.BIN.txt,这样,剧情文本ST1020AB.BIN的文本就导出了,是不是很简单?

这里放上导出的文本后翻译后的文本对照。


image


文本翻译后的检查

基于文本的越界,日文字符显示等wq做的比较完善,但是用起来还是比较麻烦,建议自己开发些工具进行修正。

image

1、文本日文字符检查


image

启动 jpcheck 1.1 ,按下检查按钮,加载翻译好的ST1020AB.BIN.txt,如果ST1020AB.BIN文本中有没有汉化的字符,程序会显示该句文本。根据offset可以查到ST1020AB.BIN文本中未翻译的日文。


问题:如果不检查,汉化后游戏中出现未汉化的文本。 2、文本格式检查

现在我们看到的导出文本格式,都是基于汉化前辈施大侠当时提出的文本格式:偏址+字节+文本,即

xxxxxxxx,xxx,文本

在文本分发翻译后,翻译在翻译过程中难免发生破坏格式的情况,如:xxxxxxxxxxx,文本以及

xxxxxxxx,xxx文本

启动文本格式检查器formatcheck 1.1,分别按下第9列和剩余列按钮加载翻译好的文本,检查文本格式是否有破坏的情况。


image

问题:如果不检查,本句文本不会被导入或者破坏被导入的文件。

3、文本字符越界检查

翻译过程中,由于为了表达清楚日文文本的含义,可能出现文本字符越界。为此需要进行检查。

启动offsetcheck1.2,由于圣女编码是sjis,属于双字节,为此我们按下双字节按钮,加载翻译好的文本进行检查,如果是utf-8编码则采用三字节按钮进行检查。

image

如果文本加入了控制符,我们还可以通过下面的控制符占用字节数进行设定。保证文本不越界。


问题:本句以下的文本不能被导入或者越界的部分不被导入。

文本导入

在上述文本检查合格后,我们可以导入文本了。启动wq。按上图的步骤完成文本的导入。至于不足部分可以用单字节20或者单字节20+双字节8140进行填充。

image

汉化的文本字符未必都是码表中的字符,导入过程中当码表中没有的字符会提示,这时还需进行修正。直至导入过程中没有提示信息,即认为大功告成。

(备注:码表中不能显示的字符工具还没写:))

问题:码表中没有的字符,本句以下的文本不能被导入,或者该字符在游戏中不能被显示。


image WQ2007-03-11版本.rar

文本导入导出器


image JP2GBK.rar SJIS码表


image WinhexV131.2SR-11.rar 16进制编辑器


image 0JPCheck.rar

日文片、平假名字符检查器


image 0FTCheck.rar文本格式检查器


image 简转繁.rar


文本的扩容


案例:圣女贞德日版ISO:PSP_GAME\SYSDIR\boot.bin 文件日文文本:

0010D140,10,ターン終了

0010D14B,6,部隊表

0010D152,4,戦況

0010D157,4,中断

0010D15C,6,ロード

0010D163,10,オプション

0010D16E,10,(クリア)

汉化文本: 0010D140,10, 回合結束

0010D14B,6,部隊表

0010D152,4,戦況

0010D157,4,中断

0010D15C,6,讀 取

0010D163,10, 選 項

0010D16E,10,(CLEAR)

image

PSP上测试效果


问题:如何将战况和中断这2个文本上下对齐?日文文本:

0010D152,4,戦況

0010D157,4,中断

显然战况和中断各占4个字节。如果采用下面的方法: 0010D152,4,戦 況

0010D157,4,中 断

显然文本越界了,各超2个字节。

image

我们用winhex来看看日文的boot.bin


image

我们用winhex来看看汉化的boot.bin


变化之处在于用20填充了不足,和文本的居中调整。战况和中断各4个字节被分隔符0A分隔,没有任何余地。如何进行扩容呢?由于汉化后长度缩短,我们用20填充,为此我们有机会利用这些20的空间来实现扩容。

答案:移动0A分隔符。

image

我们用winhex来看看汉化的且移动了0A的boot.bin


image

呵呵,我们在战况和中断间插入了双字节空格8140,来达到对齐的目的,来看看psp上的演示效果。


原先的文本offset也有了变化:汉化扩容后文本: 0010D140,10, 回合結束

0010D14B,6,部隊表

0010D152,6,戦 況

0010D159,6,中 断

0010D160,6,讀 取

0010D167,6,選 項

0010D16E,10,(CLEAR)

日文文本: 0010D140,10,ターン終了

0010D14B,6,部隊表

0010D152,4,戦況

0010D157,4,中断

0010D15C,6,ロード

0010D163,10,オプション

0010D16E,10,(クリア)

我们可以看到 0010D152,6,戦 況

0010D159,6,中 断

都增加了2个字节,也就是插入对齐用的双字节空格8140。达到了扩容的目的。注意的是:对照日文文本的offset和移动0A后的offset起始位置地址也相应地改变了。

后记:

这种情况适用于文件没有索引表的文件,如果有索引表,还得修改索引表地址,否则将不能被显示,怪物猎人2创建新人物的那个文件就采用了索引表,所以扩容更麻烦。


控制符的基本应用


WQ提供了强大的控制符应用方法,来解决诸如日文语序和中文语序颠倒的问题,还有其他诸如颜色控制等等,都可以借用控制符来导出进行修整。如何鉴别控制符的用途,还需要自己深入研究。这里我们讲解一下最简单的换行控制符的应用,可以解决日文语序和中文语序颠倒的问题。我们还是以圣女的 ST1020AB.BIN.txt为例子。


控制符(换行符)应用

image

我们先来看看圣女的剧情文本ST1020AB.BIN.txt在使用控制符(换行符)后2个文本的区别。


采用控制符(换行符)以后,优势非常明显,没有采用换行符的情况下,翻译是逐句翻译,上下文可能会出现语序颠倒的情况,当采用换行符以后,有经验的翻译可以移动换行符在本句中的位置,达到符合中国人习惯的语序。

控制符的识别

控制符的识别,老程序员靠经验就能识别,新手需要通过摸索来获得控制符的含义。就拿圣女的剧情文本ST1020AB.BIN.txt,我们用winhex来看看ST1020AB.BIN

image

OK!知道了换行符的16进制代码是0A,我们就可以利用wq提供的控制符脚本代码进行编写控制符转换了。

image

Wq控制符码表:


导出:

打开记事簿,左边填写0A,右边填写BR,(br其实是网页的硬回车,写过网页的人都知道,当然也可以

换成你喜欢的文字),导出后的结果就是: 0000198E,29,知ってるよ{BR}失敗したみたいだね导入:

左右颠倒一下。

呵呵,是不是很简单?新手可能有些困惑,但是汉化谁不是从新手一点点开始积累经验,成为老鸟?多练多实践吧。


GIM 图形格式破解


image

GIM图形格式是sony公司开发的PSP图形格式,GIM格式的版本很多,目前最新的GIM格式已经是1.40版,前段时间的游戏王使用的是1.10版本,圣女贞德采用1.10、1.20、1.30版本,鉴于目前GIM格式图像还没有图形浏览器和编辑器支持,汉化只能将GIM图形数据转换为bmp格式的图像,然后用photoshop或者 fireworks进行编辑后,重新导入GIM,达到汉化的目的。我们将以圣女贞德的GIM图形AF041_00.GIM 作为样本进行介绍,该图形在PSP_GAME\USRDIR\DATA\AS4075目录中,没有的,请下载本贴中的演示程


序。

首先我们要了解的是bmp图形格式的结构。


BMP图像格式结构表

偏移量 位数 英文解释 中文解释

0000h-0001h

2

bytes


BMP文件标识

0002h-0005h

1

dword

file size

整个文件容量

0006h-0009h

1

dword

reserved

保留


000Ah-000Dh

1

dword

bmp data offset

图像数据块开始位置(start

offset)

000Eh-0011h

1

dword

bmp head size

位图信息头

0012h-0015h

1

dword

width

位图的宽度

0016h-0019h

1

dword

height

位图的高度

001Ah-001Bh

1

word

planes

位图的位面数

001Ch-001Dh

1

word

bits per pixel

位图的信息头

001Eh-0021h

1

dword

compression

位图的压缩

0022h-0025h

1

dword

bitmap data size

位图数据块容量

0026h-0029h

1

dword

Hresolution

水平分辨率

002Ah-002Dh

1

dword

Vresolution

垂直分辨率

002Eh-0031h

1

dword

colors

位图的颜色数

0032h-0035h

1

dword

Important colors

重要颜色数


0036h

N*4 bytes

palette

调色板

N*4+1

xx bytes

bitmap data

图像数据区


GIM 图形文件结构表


image


使用winhex或ue打开AF041_00.GIM文件,结构如下。


AF041_00.GIM

文件结构


0000h-002Fh

48字节

Header

0030h-007Fh

80字节

Image header

0080h-407Fh

16384字节

ImageData

4080h-40CFh

80字节

Palette header

40D0h-44CFh

1024字节

Palette

44D0h-451Bh

76字节

FileData


ok!数据分析清楚后开始撰写bmp文件头:

42 4D

bmp标识

42 4D 36 44 00 00

bmp标识+bmp文件长度

注:文件长度获得:看上表,bmp头文件54字节+调色板(256色)1024字节+图像数据16384字节=17462字节(10进制)=4436字节 (16进制)

42 4D 36 44 00 00 00 00 00 00

bmp标识+bmp文件长度+保留

42 4D 36 44 00 00 00 00 00 00 36 04 00 00

bmp标识+bmp文件长度+保留+图像数据开始位置

注:图像数据开始位置=bmp文件头54字节+256色调色板1024字节=1078字节(10进制)=436字节(16进制)

42 4D 36 44 00 00 00 00 00 00 36 04 00 00 28 00 00 00

bmp标识+bmp文件长度+保留+图像数据开始位置+windows操作系统标识

42 4D 36 44 00 00 00 00 00 00 36 04 00 00 28 00 00 00 80 00 00 00

bmp标识+bmp文件长度+保留+图像数据开始位置+windows操作系统标识+图像宽度注:图形宽度在AF041_00.GIM 的0048h,即10进制128像素。

42 4D 36 44 00 00 00 00 00 00 36 04 00 00 28 00 00 00 80 00 00 00 80 00 00 00

bmp标识+bmp文件长度+保留+图像数据开始位置+windows操作系统标识+图像宽度+图像高度注:图形高度在AF041_00.GIM 的004Ah,即10进制128像素。

42 4D 36 44 00 00 00 00 00 00 36 04 00 00 28 00 00 00 80 00 00 00 80 00 00 00 01 00

bmp标识+bmp文件长度+保留+图像数据开始位置+windows操作系统标识+图像宽度+图像高度+位面数注:位面数 01 00 照抄可以了。

42 4D 36 44 00 00 00 00 00 00 36 04 00 00 28 00 00 00 80 00 00 00 80 00 00 00 01 00 08 00

bmp标识+bmp文件长度+保留+图像数据开始位置+windows操作系统标识+图像宽度+图像高度+位面数+图像信息头

注:图像信息头:16色-4 ,256色-8,16兆色-16,24兆色-18,32兆色-32。

42 4D 36 44 00 00 00 00 00 00 36 04 00 00 28 00 00 00 80 00 00 00 80 00 00 00 01 00 08 00

00 00 00 00

bmp标识+bmp文件长度+保留+图像数据开始位置+windows操作系统标识+图像宽度+图像高度+位面数+图像信息头+压缩

注:压缩:无压缩,全填00。

42 4D 36 44 00 00 00 00 00 00 36 04 00 00 28 00 00 00 80 00 00 00 80 00 00 00 01 00 08 00

00 00 00 00 00 40 00 00

bmp标识+bmp文件长度+保留+图像数据开始位置+windows操作系统标识+图像宽度+图像高度+位面数+图像信息头+压缩+图像数据长度

注:图像数据长度:上表中16384字节=4000字节(16进制)。

42 4D 36 44 00 00 00 00 00 00 36 04 00 00 28 00 00 00 80 00 00 00 80 00 00 00 01 00 08 00

00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00

bmp标识+bmp文件长度+保留+图像数据开始位置+windows操作系统标识+图像宽度+图像高度+位面数+图像信息头+压缩+图像数据长度+水平分辨率+垂直分辨率

42 4D 36 44 00 00 00 00 00 00 36 04 00 00 28 00 00 00 80 00 00 00 80 00 00 00 01 00 08 00

00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 01 00 00

bmp标识+bmp文件长度+保留+图像数据开始位置+windows操作系统标识+图像宽度+图像高度+位面数+图像信息头+压缩+图像数据长度+水平分辨率+垂直分辨率+颜色数

注:颜色数:256色=100H

42 4D 36 44 00 00 00 00 00 00 36 04 00 00 28 00 00 00 80 00 00 00 80 00 00 00 01 00 08 00

00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00

bmp标识+bmp文件长度+保留+图像数据开始位置+windows操作系统标识+图像宽度+图像高度+位面数+图像信息头+压缩+图像数据长度+水平分辨率+垂直分辨率+颜色数+重要颜色数

注:无

OK!bmp文件头写好了:

42 4D 36 44 00 00 00 00 00 00 36 04 00 00 28 00 00 00 80 00 00 00 80 00 00 00 01 00 08 00

00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00

用winhex或ue新建一个16进制文件,写入上面的文件头,把gim的调色板1024字节复制过来,紧接bmp文件头,下面就是图像数据16384字节了,完成后另存为bmp即可现在可以用图像浏览器观看了。

image

晕,图像是对了,但是出现颠倒和颜色不对。

原来bmp和gim的描绘方式不同,我们需要纠正一下,询问了aeolusc大大,提供了经典的解决方案,高度置于负数 80 FF FF FF,我们再来看一下。

image

罗杰的衣服颜色怎么蓝了?原来GIM的颜色通道是BGRA,我们需要将调色板的256组BGRA的“B"和”

R“对换一下成为RGBA,这个用手工的话要死人的,还是写个程序转换吧,然后再来看看

image

总算写完了,累死了。

最后,修改好的bmp导入,可采用上诉逆序的方法导入。下面的GIMtoBMP演示程序,可以帮助你了解破解的过程!


image

gim格式版本很多,本方法不能通用,具体情况还需具体分析,破解前还是要用winhex和ue看一下结构再下手。

image gimtools演示程序.rar


GIM 图像格式破解 第二篇


上一讲中我们提到的是最基本的GIM图形格式,其图形数据区在转为bmp图像格式时,可以直接提取GIM的imagedata,也就是说,此种格式的GIM图像数据区的描绘方式和bmp的描绘方式相同,即在宽度范围内从左至右一直描绘到图像宽度结束。而本讲提出的问题是当GIM采用16x8或16x16的描绘方式时,如果采用上面的直接提取imagedata方式导入bmp,则会出现贴图错误。下面我们来分析一下16x8描绘的原 理。我们以游戏王的t_window0026.gim为例子。它的几何尺寸为64x32像数。标准的16x8存储描绘方

式。本次演示程序可在下面下在,1.1版本为对16x8进行处理,1.2版针对t_window0026.gim的16x8存储描绘方式进行了处理。大家可以打开看一下,加深理解。


image

我们来看看实际情况图。

下面这张使用1.1版本打开conv目录下的t_window0026.gim,这是图像数据未经16x8处理的


image

image

下面这张使用1.2版本打开conv目录下的t_window0026.gim,这是图像数据经16x8处理的


我们将未经16x8处理的t_window0026.gim放大10倍来看,很明显图像分成了4列,对照上面的描绘方式图,大家就不能难理解了。


image

我们通过提取t_window0026.gim的图像数据区共2048个字节,完成描绘16x8存储小块需要2048/(16x8)

=16块,再来看看t_window0026.gim的图形尺寸,64x32像素,即而完成

宽度一次描绘需要64个字节。而完成一次高度描绘需要8个字节,那么总计完成一次以宽度为单位描绘则需要64x8=512字节。那么图形数据2048需要描绘几次才能完成呢?答案2048/512=4次。我们再来看看下面的数据区重新组合演示。


image

上图就是从gim文件中提取2048字节的图形数据区块的1/4数据快(512字节)转bmp数据块512字节的演示图,其他3块(512字节)的方法相同,大家也看到,这种重新排列的方法靠手动调整是不可能实现的,现在仅仅只有2kb的数据,而目前已知的最大gim数据区有128kb。为此还是需要编程来完成数据的重整。

ps:如果gim图像尺寸是128x32呢?呵呵,这种算法只要在上面的算法上改进一下即可,1.3版演示程序可以看conv目录128x32的gim。


image gimtools 1.2演示程序.rar image gimtools1.3演示程序.rar

diff --git a/docs/archive/bluekiller_files/Image_001.jpg b/docs/archive/bluekiller_files/Image_001.jpg new file mode 100644 index 0000000..c5b31cc Binary files /dev/null and b/docs/archive/bluekiller_files/Image_001.jpg differ diff --git a/docs/archive/bluekiller_files/Image_002.jpg b/docs/archive/bluekiller_files/Image_002.jpg new file mode 100644 index 0000000..19b9d36 Binary files /dev/null and b/docs/archive/bluekiller_files/Image_002.jpg differ diff --git a/docs/archive/bluekiller_files/Image_003.jpg b/docs/archive/bluekiller_files/Image_003.jpg new file mode 100644 index 0000000..f449146 Binary files /dev/null and b/docs/archive/bluekiller_files/Image_003.jpg differ diff --git a/docs/archive/bluekiller_files/Image_004.jpg b/docs/archive/bluekiller_files/Image_004.jpg new file mode 100644 index 0000000..76729e1 Binary files /dev/null and b/docs/archive/bluekiller_files/Image_004.jpg differ diff --git a/docs/archive/bluekiller_files/Image_005.png b/docs/archive/bluekiller_files/Image_005.png new file mode 100644 index 0000000..8f6b9fa Binary files /dev/null and b/docs/archive/bluekiller_files/Image_005.png differ diff --git a/docs/archive/bluekiller_files/Image_006.jpg b/docs/archive/bluekiller_files/Image_006.jpg new file mode 100644 index 0000000..f3573a8 Binary files /dev/null and b/docs/archive/bluekiller_files/Image_006.jpg differ diff --git a/docs/archive/bluekiller_files/Image_007.jpg b/docs/archive/bluekiller_files/Image_007.jpg new file mode 100644 index 0000000..5bad7cc Binary files /dev/null and b/docs/archive/bluekiller_files/Image_007.jpg differ diff --git a/docs/archive/bluekiller_files/Image_008.png b/docs/archive/bluekiller_files/Image_008.png new file mode 100644 index 0000000..d8c8c2c Binary files /dev/null and b/docs/archive/bluekiller_files/Image_008.png differ diff --git a/docs/archive/bluekiller_files/Image_009.png b/docs/archive/bluekiller_files/Image_009.png new file mode 100644 index 0000000..d8c8c2c Binary files /dev/null and b/docs/archive/bluekiller_files/Image_009.png differ diff --git a/docs/archive/bluekiller_files/Image_010.png b/docs/archive/bluekiller_files/Image_010.png new file mode 100644 index 0000000..d8c8c2c Binary files /dev/null and b/docs/archive/bluekiller_files/Image_010.png differ diff --git a/docs/archive/bluekiller_files/Image_011.png b/docs/archive/bluekiller_files/Image_011.png new file mode 100644 index 0000000..d8c8c2c Binary files /dev/null and b/docs/archive/bluekiller_files/Image_011.png differ diff --git a/docs/archive/bluekiller_files/Image_012.png b/docs/archive/bluekiller_files/Image_012.png new file mode 100644 index 0000000..d8c8c2c Binary files /dev/null and b/docs/archive/bluekiller_files/Image_012.png differ diff --git a/docs/archive/bluekiller_files/Image_013.png b/docs/archive/bluekiller_files/Image_013.png new file mode 100644 index 0000000..d8c8c2c Binary files /dev/null and b/docs/archive/bluekiller_files/Image_013.png differ diff --git a/docs/archive/bluekiller_files/Image_014.jpg b/docs/archive/bluekiller_files/Image_014.jpg new file mode 100644 index 0000000..8244564 Binary files /dev/null and b/docs/archive/bluekiller_files/Image_014.jpg differ diff --git a/docs/archive/bluekiller_files/Image_015.jpg b/docs/archive/bluekiller_files/Image_015.jpg new file mode 100644 index 0000000..536d92e Binary files /dev/null and b/docs/archive/bluekiller_files/Image_015.jpg differ diff --git a/docs/archive/bluekiller_files/Image_016.jpg b/docs/archive/bluekiller_files/Image_016.jpg new file mode 100644 index 0000000..77710fc Binary files /dev/null and b/docs/archive/bluekiller_files/Image_016.jpg differ diff --git a/docs/archive/bluekiller_files/Image_017.jpg b/docs/archive/bluekiller_files/Image_017.jpg new file mode 100644 index 0000000..763475f Binary files /dev/null and b/docs/archive/bluekiller_files/Image_017.jpg differ diff --git a/docs/archive/bluekiller_files/Image_018.jpg b/docs/archive/bluekiller_files/Image_018.jpg new file mode 100644 index 0000000..67a345f Binary files /dev/null and b/docs/archive/bluekiller_files/Image_018.jpg differ diff --git a/docs/archive/bluekiller_files/Image_019.jpg b/docs/archive/bluekiller_files/Image_019.jpg new file mode 100644 index 0000000..877702a Binary files /dev/null and b/docs/archive/bluekiller_files/Image_019.jpg differ diff --git a/docs/archive/bluekiller_files/Image_020.jpg b/docs/archive/bluekiller_files/Image_020.jpg new file mode 100644 index 0000000..edebb13 Binary files /dev/null and b/docs/archive/bluekiller_files/Image_020.jpg differ diff --git a/docs/archive/bluekiller_files/Image_021.jpg b/docs/archive/bluekiller_files/Image_021.jpg new file mode 100644 index 0000000..a9edfa7 Binary files /dev/null and b/docs/archive/bluekiller_files/Image_021.jpg differ diff --git a/docs/archive/bluekiller_files/Image_022.jpg b/docs/archive/bluekiller_files/Image_022.jpg new file mode 100644 index 0000000..6b680e7 Binary files /dev/null and b/docs/archive/bluekiller_files/Image_022.jpg differ diff --git a/docs/archive/bluekiller_files/Image_023.jpg b/docs/archive/bluekiller_files/Image_023.jpg new file mode 100644 index 0000000..0c06bf8 Binary files /dev/null and b/docs/archive/bluekiller_files/Image_023.jpg differ diff --git a/docs/archive/bluekiller_files/Image_024.jpg b/docs/archive/bluekiller_files/Image_024.jpg new file mode 100644 index 0000000..f586465 Binary files /dev/null and b/docs/archive/bluekiller_files/Image_024.jpg differ diff --git a/docs/archive/bluekiller_files/Image_025.jpg b/docs/archive/bluekiller_files/Image_025.jpg new file mode 100644 index 0000000..36d290c Binary files /dev/null and b/docs/archive/bluekiller_files/Image_025.jpg differ diff --git a/docs/archive/bluekiller_files/Image_026.jpg b/docs/archive/bluekiller_files/Image_026.jpg new file mode 100644 index 0000000..1b79095 Binary files /dev/null and b/docs/archive/bluekiller_files/Image_026.jpg differ diff --git a/docs/archive/bluekiller_files/Image_027.jpg b/docs/archive/bluekiller_files/Image_027.jpg new file mode 100644 index 0000000..2b12ede Binary files /dev/null and b/docs/archive/bluekiller_files/Image_027.jpg differ diff --git a/docs/archive/bluekiller_files/Image_028.png b/docs/archive/bluekiller_files/Image_028.png new file mode 100644 index 0000000..d8c8c2c Binary files /dev/null and b/docs/archive/bluekiller_files/Image_028.png differ diff --git a/docs/archive/bluekiller_files/Image_029.jpg b/docs/archive/bluekiller_files/Image_029.jpg new file mode 100644 index 0000000..763bb9b Binary files /dev/null and b/docs/archive/bluekiller_files/Image_029.jpg differ diff --git a/docs/archive/bluekiller_files/Image_030.jpg b/docs/archive/bluekiller_files/Image_030.jpg new file mode 100644 index 0000000..0b9cd5a Binary files /dev/null and b/docs/archive/bluekiller_files/Image_030.jpg differ diff --git a/docs/archive/bluekiller_files/Image_031.jpg b/docs/archive/bluekiller_files/Image_031.jpg new file mode 100644 index 0000000..93adff9 Binary files /dev/null and b/docs/archive/bluekiller_files/Image_031.jpg differ diff --git a/docs/archive/bluekiller_files/Image_032.jpg b/docs/archive/bluekiller_files/Image_032.jpg new file mode 100644 index 0000000..762fba3 Binary files /dev/null and b/docs/archive/bluekiller_files/Image_032.jpg differ diff --git a/docs/archive/bluekiller_files/Image_033.jpg b/docs/archive/bluekiller_files/Image_033.jpg new file mode 100644 index 0000000..c0339a5 Binary files /dev/null and b/docs/archive/bluekiller_files/Image_033.jpg differ diff --git a/docs/archive/bluekiller_files/Image_034.png b/docs/archive/bluekiller_files/Image_034.png new file mode 100644 index 0000000..d8c8c2c Binary files /dev/null and b/docs/archive/bluekiller_files/Image_034.png differ diff --git a/docs/archive/bluekiller_files/Image_035.png b/docs/archive/bluekiller_files/Image_035.png new file mode 100644 index 0000000..d8c8c2c Binary files /dev/null and b/docs/archive/bluekiller_files/Image_035.png differ diff --git a/docs/archive/readme.md b/docs/archive/readme.md new file mode 100644 index 0000000..3e9de1e --- /dev/null +++ b/docs/archive/readme.md @@ -0,0 +1 @@ +本文件夹内为互联网中存档,版权归原作者所有。 \ No newline at end of file diff --git a/docs/debug.md b/docs/debug.md index 94932a3..bce9fba 100644 --- a/docs/debug.md +++ b/docs/debug.md @@ -20,11 +20,12 @@ 使用实机Debug有很多好处 ## Debug Using `PPSSPP` -> [《诡计对逻辑》汉化研究](https://pbteam.cn/posts/txl-hack/) -> https://datacrystal.romhacking.net/wiki/Blaze_Union/Tutorials -> https://github.com/Bunkai9448/digipet_PSP/blob/main/RE_Guide.md +> + [《诡计对逻辑》汉化研究](https://pbteam.cn/posts/txl-hack/) +> + https://datacrystal.romhacking.net/wiki/Blaze_Union/Tutorials +> + https://github.com/Bunkai9448/digipet_PSP/blob/main/RE_Guide.md PPSSPP自带的调试工具算很强大了。简要介绍一下它的功能。 + + 查看寄存器 + 查看内存 + 给系统调用打断点 @@ -32,10 +33,13 @@ PPSSPP自带的调试工具算很强大了。简要介绍一下它的功能。 具体用法可以参考链接。 几种内存地址的变换 + + psp的内存地址空间 + Dump出的内存 + ELF中的vmaddr + ELF的二进制文件 -## Makefile Example (From RetroArch) +### Debug using `PPSSPP` with `Ghidra` + +## Makefile Example (From `RetroArch`) + After `include` \ No newline at end of file diff --git a/docs/libs/font.md b/docs/libs/font.md index bf7c97c..cca0ea1 100644 --- a/docs/libs/font.md +++ b/docs/libs/font.md @@ -10,4 +10,24 @@ UCS2,可认为是UTF-16用二个字节来表示基本平面 UTF-16 编码表 Unicode 中的一个编码区段,编码从 U+0000 至 U+FFFF,也称基本多文种平面(Basic Multilingual Plane,BMP),或第零平面(Plane 0)。 -Unicode 编码规定以下字符范围为控制字符,\U0000 - \U001F, \U007F, \U0080 - \U009F。 \ No newline at end of file +Unicode 编码规定以下字符范围为控制字符,\U0000 - \U001F, \U007F, \U0080 - \U009F。 + +# PGF + +26.9 PGF + +The PSP font format (.PGF files) is a bitmap based font format. Each letter (as well as its shadow) is a single, 4bpp bitmap, saved in the font file in a RLE compressed form. The bitmaps are encoded using either vertical or horizontal rows, depending on a certain 2-bit field in character metrics. Every [character, shadow] bitmap pair is preceded by a character metrics record. For Latin fonts the length of this record appears to be 12 bytes (with an optional 7-byte extension), for other families it's different. It's not known at this time what is the determinant of the record length. The metrics record contains the following fields: +14-bit offset of the shadow header record +7-bit width +7-bit height +7-bit signed horizontal adjustment +7-bit ascender +2-bit transposition (1 - horizontal rows, 2 - vertical rows) +1-bit modified record field (adds a 7-byte extension to the 12-byte header for ltn0.pgf) +46 bits of unknown data +5-bit horizontal advance +To find the character metrics one has to read the main pointer table. The table is constructed of N-bit pointers, where N is found in the file header at offset 0x1C. The number of pointers (and characters) can be found in the file header at offset 0x14. It is not known yet how to locate the main pointer table. The RLE compression works on 4-bit nibbles (the low nibble of a byte is considered to precede the high nibble in the stream). There are two sequences defined for this RLE: +a nibble N<8: take next nibble and replicate N+1 times into the output stream +a nibble N>7: take next 16-N nibbles and copy directly into the output stream + +上面的文章好像是针对拉丁字符的,中文字符感觉要参考一下国内的程序,或者PPSSPP。 \ No newline at end of file diff --git a/docs/profiling.md b/docs/profiling.md new file mode 100644 index 0000000..0ad67f0 --- /dev/null +++ b/docs/profiling.md @@ -0,0 +1,11 @@ +# Profiling +PSP Toolchain 支持 `gprof`(GNU Prof)。 +## GNU Prof +### 使用方法 +1. 编译程序 +直接编译: +链接: +2. 生成.out +3. 使用gprof分析.out文件。 + +参考资料:gprof官网 \ No newline at end of file diff --git a/docs/stublibs.md b/docs/stublibs.md index bc55007..1a70083 100644 --- a/docs/stublibs.md +++ b/docs/stublibs.md @@ -21,29 +21,36 @@ ## 编写可被其他模块动态加载的PRX模块 > A PRX-format module can be used as a resident library. A resident library provides some of its functions to another module. -编写导出表,将导出表嵌入PRX模块。 - -1. 撰写PRX程序的C代码 -不写main函数,写module_start()和module_stop()函数 -注意:请于module_start()函数中加一行`printf()`函数调用,否则在由ELF文件生成PRX文件时会出现缺少.lib.stub段的问题(WHY?)。 -2. 编写导出表,指定哪些函数可被其他模块引用 -导出格式。 -必须导出: -自定义导出: -据说不推荐导出变量。 -3. 对导出表使用`psp-build-exports -b`生成C代码 - ### build.mak - ```makefile +我们通过编写**导出表**来指定自己模块中哪些函数可以被外部访问 + +并通过向模块使用者提供**导入表**使其能引入自己的模块。 + +由于使用者能够**导入**的函数也就是编写者**导出**的函数, + +我们只需要编写一次导出表,就可以通过导出表生成导入表。 + +### Step 1:编写导出表,将导出表嵌入PRX模块。 + +1. 撰写PRX程序的C代码:不写`main`函数,写`module_start()`和`module_stop()`函数 +>!!! Hint + 注意:请于module_start()函数中加一行`printf()`函数调用,否则在由ELF文件生成PRX文件时会出现缺少.lib.stub段的问题(WHY?)。 +1. 编写导出表(`.exp`后缀的文本文件),指定哪些函数可被其他模块引用 +> 导出格式。 +> +> + 必须导出: +> + 自定义导出: +> +> 据说不推荐导出变量。 +2. 对导出表使用`psp-build-exports -b`生成C代码 + ```makefile title="build.mak" %.c: %.exp psp-build-exports -b $< > $@ ``` -4. 编译1、3中的C代码得到可重定位目标文件,链接后生成PRX文件 - ### build.mak - ```makefile - # 将3中C代码对应的目标文件设为构建目标 - ifdef PRX_EXPORTS - EXPORT_OBJ=$(patsubst %.exp,%.o,$(PRX_EXPORTS)) - EXTRA_CLEAN += $(EXPORT_OBJ) +3. 将步骤3中的C代码进行编译,与源程序相链接,从而将导出表信息嵌入源程序。 + ```makefile title="build.mak" + ifdef PRX_EXPORTS # 预先指定 PRX_EXPORTS = your_name.exp + EXPORT_OBJ=$(patsubst %.exp,%.o,$(PRX_EXPORTS)) # 将其纳入构建目标 + EXTRA_CLEAN += $(EXPORT_OBJ) # 将可重定位目标文件纳入clean目标 ``` ```makefile # 编译链接 @@ -52,13 +59,21 @@ $(FIXUP) $@ ``` 注意,链接时需要指定`LDFLAGS = -nostartfiles`以避免出现`main`函数符号未定义的问题。 + **至此,导出表已嵌入PRX文件,接下来的步骤是为将要使用该PRX文件的模块准备的** -5. 对导出表使用`psp-build-exports -k`生成存根.S文件(module stubs / import table) -6. (可选)编译.S文件至.o文件并通过ar即得到存根库 + +### Step 2: 从导出表生成导入表 +1. 对上一步编写的导出表使用`psp-build-exports -k`生成存根.S文件(module stubs / import table) +2. (可选)编译`.S`存根文件至`.o`可重定位目标文件并通过ar打包成`.a`静态链接库存档文件即得到存根库 ## 在程序中动态加载PRX模块 + 写代码时:包含存根库的头文件 -+ 链接时:编译存根.S文件并与之链接 / 链接存根库 +使用PSPSDK中加载动态库的函数 +sceKernelLoadModule +sceKernelFindModuleByUID +sceKernelStartModule + ++ 链接时:编译存根`.S`文件至并与之链接 / 链接存根库 `OBJS`中指定.S->.o的文件名 diff --git a/docs/translate.md b/docs/translate.md index b878006..627716f 100644 --- a/docs/translate.md +++ b/docs/translate.md @@ -1,20 +1,60 @@ # Language Patch -这篇文章写的太好了,我觉得没必要再多说什么了。 -https://github.com/Bunkai9448/digipet_PSP/blob/main/RE_Guide.md + +这篇[Digivice Ver. Portable逆向工程教程](https://github.com/Bunkai9448/digipet_PSP/blob/main/RE_Guide.mdDigivice)写的太好了,涉及从逆向到发布的全过程与工具链,我觉得没必要再多说什么了。 + +> [digipet_PSP/RE_Guide.md](https://github.com/Bunkai9448/digipet_PSP/blob/main/RE_Guide.mdDigivice) # 汉化相关 +## 传统汉化方法 +> !!! Hint +> + 码表:即编码字节同字符的对应表。 +> +> + 字库:即储存字体字形图像的文件。 -都是2010年前后,上个时代的资料了。现在的人应该用更现代的语言来表述。使用现代的工具链! +从二进制文件中检测潜在的字符串并生成<偏移量,字符数,字符内容>的一张表。通过这张表可以方便地对源文件进行替换和修改。 + +为了检测潜在的字符串,需要**编码字节与字符的对应表**,即“**码表**” + +由于游戏通常采用[SHIFT-JIS](http://www.rikai.com/library/kanjitables/kanji_codes.sjis.shtml)编码,而该编码中汉字字符数量极为有限。 -https://xiongonline.github.io/[%E8%BD%AC%E8%BD%BD][NDS]NDS%E6%B1%89%E5%8C%96%E5%B0%8F%E7%99%BD%E6%95%99%E7%A8%8B.html#top +因而人们会**修改字体文件**,即“**字库**”,将原来的SHIFT-JIS字节序列对应的日文字符图像修改为其他的汉字字符图像。 -https://www.romhacking.net/utilities/818/ +此时字节序列同字符的对应关系已然发生改变。 -https://bbs.chengyi.org/thread-111286-1-1.html +因而又要重新写一张字符和编码字节的对应表,将翻译后的文本映射到新的字节序列上。 -近似字符表:https://github.com/ultrapre/GBK_SJIS/blob/master/gbksjisTBL/README.md +此时再对源二进制文件中的字符序列进行替换修改,便完成了文本的汉化过程。 + +> 参考资料 +> +> 码表相关 +> +> + [【GBA、NDS、PSP】汉化基础教程——文字篇(三)by PGCG](https://bbs.chengyi.org/thread-111286-1-1.html) +> + [NDS汉化小白教程 —— fengarea(A9VG汉化组)](https://xiongonline.github.io/[%E8%BD%AC%E8%BD%BD][NDS]NDS%E6%B1%89%E5%8C%96%E5%B0%8F%E7%99%BD%E6%95%99%E7%A8%8B.html#top) 第三话:字库码表篇•初步 +> + [游戏汉化教学贴-文本的导入导出基础篇](archive/bluekiller.htm) + +### 理想情况 +能够从二进制文件和资源文件中找到字符串和字库,直接进行修改。 +在2010年左右,`WQSG`和`CrystalScript`用于处理码表、检测二进制文件中潜在的字符串,`CrystalTile`用于处理二级制文件中的图片和字库。 +> 参考资料 +> [CrystalTile](https://www.romhacking.net/utilities/818/) +### 无法获得字符串或字库 +由于加密等问题,汉化工作者有时无法从二进制文件中寻找到字符串和字库。此时往往有以下两种方法。 +#### 近似汉化 +在无法获得字库时,使用SHIFT-JIS中已有的同汉字相近的日文字符作为对应汉字的替代。 +> 近似字符表:https://github.com/ultrapre/GBK_SJIS/blob/master/gbksjisTBL/README.md +#### 内存汉化 +无法在源文件中获得字符串或字库,但由于游戏运行时未加密的字符串和字库会加载到内存中,因而可以通过插件在游戏运行时对内存相应区域进行替换修改。 +> [CG汉化组-幻想传说汉化测试插件](http://bbs1.chinaemu.org/read-htm-tid-80057-uid-71886.html) + +## 具体实现 +都是2010年前后,上个时代的资料了。现在的人应该用更现代的语言来表述。使用现代的工具链! +### 仅仅对文件修改 +按照传统的汉化方法,只需要对资源文件和可执行文件中出现的代表字符串的`字节序列`和`字库`进行修改汉化工作便完成了。这一步的难点就在文件格式的解密上。 -SHIFTJIS表:http://www.rikai.com/library/kanjitables/kanji_codes.sjis.shtml +具体来讲,对于`PSP`汉化,可以通过`PPSSPP`的调试功能逐步分析文件格式。可以参考[《诡计对逻辑》汉化研究](https://pbteam.cn/posts/txl-hack/) +### 修改可执行文件/添加外部插件 +对于一些需要使用内存汉化法或者调用的是系统字库的游戏,则需要进行程序逻辑的修改或者编写新的插件。也就是要进行反汇编、注入、劫持等操作。这更接近于本网站的主题。 https://uofw.github.io/upspd/docs/software/ModuleTutorialv1.pdf @@ -31,4 +71,4 @@ v0:0x539F 8CB4-> 539F -08868dac调用sceFontGetCharInfo和sceFontGetCharGlyph \ No newline at end of file +08868dac调用sceFontGetCharInfo和sceFontGetCharGlyph