写在前面

仓库地址:https://github.com/wetor/LucaSystemTools
最新Release:LucaSystemTools_20201214(v1.0.1)

此工具虽然是针对某些文字游戏的游戏引擎的,作用也仅仅是能提取资源、修改导入资源而已,或者是翻译游戏之类的,但是这也算我第一个真正意义上的多人协作项目。

部分代码的实现、到仓库的管理,DeQxJ00给了我很大的帮助,从早期的PSV《白色相簿2》的移植汉化,到LucaSystemTools中,特别是图像处理和解压方面,几乎都是他所编写的。

还有后来加入的DevSeed,如果不是他要搞PSV《AIR》的汉化,这个项目估计早就凉了。也是因为DevSeed,我们才搞了好几个游戏的汉化(虽然目前只完整弄好一个,但是实际上文本部分完成的总共有三四个)。

还有因为《Robotics;Notes》相关汉化而加入的未来,后续也接手了PSV《ISLAND》的移植汉化文本处理,以及冂字同桌也对PSV《ISLAND》文本处理提供了帮助,

Github活动

2019-7-23

Commit

暑假留校,在信息安全工作室学习逆向,作为课题(以及爱好)研究了Prototype公司Nintendo Switch(以下简称NS)平台游戏《Summer Pockets》上所使用的新游戏引擎LucaSystem
在研究完成后所写的博客:

Summer Pockets(以下简称SP)是Key社的一款文字冒险游戏,NS的移植发行商为Prototype(一下简称prot) ,该公司移植了很多文字冒险游戏到主机平台,如Flowers,Island,Clannad等,如同预期的那样,都没有中文。

今年年初曾和大佬DeQxJ00研究过PSV island的汉化可行性(在我发帖之后),并成功完成了一些列必要工具,如字库(CZ1格式)图像的解压与压缩,字体info文件的提取等。CZ1和info文件相关文档和源码以后会写的…(咕咕咕)

在解包SP的资源后,pak包直接用https://github.com/marcussacana/LucaSystem 解包,打包稍微写了一下也OK,字库直接用DeQxJ00的CZ1工具也没问题,主要就是脚本文件了。

本来island的脚本解析就没有完全完成就因为文本处理工作量大而放弃了,SP的脚本有与之有点区别,于是着手脚本的研究。期间找到了SP PC版汉化组并要到了序章的文本,以便测试使用。

初期的研究是完全用010Editor分析字节,找出了文本位置的规律,后来在解析更多“规律”时,意外发现了prot脚本的执行方式,大概是同汇编一样(不过不同还挺多的),通过一个短整数确定接下来一条指令和参数的长度,然后以此循环,直到脚本结束。

然后又幸通过IDA找了到脚本解析的相关代码(虽然没看懂),发现了诸如

OPCODE指令码列表:

使用OPCODE进行输出的部分函数:

之类的有趣东西,简单对比,脚本的格式大致为:

其中code字节中的第一个字节通过字典索引就是IDA里的指令文本!
接着分析了许多包含字符串的指令参数,就能解出一下样式的脚本:

之后稍微写了一下编译程序,基本的脚本就解析完成!
配合上deqxj00所实现的CZ1图像解析以及FontInfo文件的解析,一定可以进行汉化的。

CZ1图像与FontInfo字库解析是在今年(2019)年年初昨晚《白色相簿2》移植汉化后,对于PSV《Island》所研究的,实际上ISLAND所使用的LucaSystem引擎是更早期的版本,脚本解析部分并不能直接使用。

创建Github仓库:PrototypeTools,基础代码为Forkmarcussacana/LucaSystem此仓库。删除了marcussacana/LucaSystem的GUI,增加了CZ1、FontInfo文件解析以及《Summer Pockets》脚本解析。

2019-7-24

Commit

优化《Summer Pockets》脚本解析代码,使用C#的不定参数,实现根据传入不同的参数类型,按这些参数类型进行二进制读取,返回解析后的指令文本。

得益于使用一个函数来读取几乎所有OPCODE代码,增加了几个指令的支持,也为后续增加更多指令提供了方便。

2019-7-25

  1. 支持反编译成文本后,再编译成脚本,支持修改数据。 Commit
  2. 将2019年1月份研究《ISLAND》时所编写的CZ1图像生成代码,以及其PAK文件解包代码整合进PrototypeTools。 Commit
  3. 支持PAK文件的打包。 Commit

2019-7-29

Commit

我和DeQxJ00通过以前的CZ1代码,以及对CZ3文件的分析,完成了CZ3图像提取与制作的代码。

CZ3在压缩方面和CZ1相同,都是LZW压缩,但是CZ3解压后的数据,并不是一个完整的图像,而是一个图像有几行为正确颜色的’基准行’,其他行颜色都是根据这个’基准行’进行计算将得到的差值进行储存。这么做是牺牲了部分IO效率,提高LZW的压缩效率。生成CZ3算法只需按照这个步骤对CZ1算法进行修改,提取算法则根据这个进项逆向运算即可得到正确图像。

2019-7-30

Commit

支持了NS《Clannad》的脚本提取,由于游戏不同,所以指令的参数也不尽相同,所以并不能用同一份代码实现对Clannad的完美提取。

同时为了支持第二个游戏,是程序能够自己选择要加载的OPCODE,之后扩充游戏支持列表也更方便。

2020-5-24

在贴吧发现DevSeed对于PSV《AIR》汉化过程中对类似CZ1的Dat格式图像有疑问,故和他共享此仓库。

项目重启。

仓库改名为LucaSystemTools,目的是支持更多同样引擎的游戏。

2020-5-25

Commit

在通过和DevSeed、DeQxJ00的交流后,我发现了DAT图像与CZ图像的区别,DAT图像在LZW解压后,RGBA为0的颜色,均转为255。

解出来的正确图像

顺便在研究《AIR》psb脚本文件时,发现此脚本的跳转是在每条指令的最后,0xA3 0xA4都是跳转指令

具体的《AIR》汉化脚本在 DevSeed《AIR》汉化代码,包含了psb脚本的修改以及dat图像的解析与制作。

DAT图像还有对应着CZ3的’基准行’类型的,稍微修改之前的代码也能解出来
DAT图像的几次Commit Commit1 Commit2

2020-5-28

Commit

因为此工具并没有可视化界面,所以由 DeQxJ00 将此项目转为.NetCore,支持多平台。

2020-5-29

Commit

发现DAT图像RGBA颜色并非如果是0就变成255(见2020-5-25),而是均减去1,对于byte类型来说,0-1会发生溢出,结果为255

2020-5-30

更新README,将各个文件的作用写清楚,并列出支持的游戏。

2020-8-1

Commit1 Commit2

重构ScriptOpcode.cs,现在能够在OPCODE.txt中设置每个指令的类型了!也就是说只要OPCODE.txt编写好,只要程序支持,都能正确的解析出脚本了。

支持了PSV《ISLAND》的解析,因为语法规则与NS《Summer Pockets》有所出入,还有一个PSV《AIR》脚本也不同,所以我根据使用引擎的游戏发售时间,暂定

  • PSV《AIR》为LucaSystem脚本Ver1;
  • PSV《ISLAND》为LucaSystem脚本Ver2;
  • NS《Summer Pockets》为LucaSystem脚本Ver3。

2020-8-2

Commit

支持《ISLAND》脚本编译,得益于昨天进行的适配化修改,只需要针对Ver2脚本调整格式即可。

2020-9-8

Commit

支持DevSeed新发现的CZ4图像提取

2020-9-9

DeQxJ00重构部分CZ图像代码,支持Github Action自动编译
仓库代码

2020-9-13

Commit

支持刚发售的NS《Tomoyo After Its a Wonderful Life CS Edition》(智代后记:美丽的生活)脚本提取。

因为这个游戏是日文和英文双语,结构与之前有所不同,所以添加了新的字符串类型以及适配。

2020-9-14

Commit

支持《Tomoyo After Its a Wonderful Life CS Edition》的完整反编译与编译,同时为了解决多游戏适配,适当修改了代码。

2020-9-16

Commit

支持NS《Flowers - Shiki》脚本的编译与反编译。

支持的游戏越来越多,每次都需要修改源代码添加新的OPCODE文件,所以这次也支持了自定义OPCODE,只要在命令行中指定即可。

2020-9-17 ~ 2020-9-29

由于DevSeed在汉化《Air》时在字库打包上遇到了问题,所以我们开始对以前仅有提取功能的FontInfo代码修改,虽然主要都是DeQxJ00在改。字库方便也都是交由他负责的,我主要是脚本方面。

DeQxJ00完成了字库方面的打包,但是原本的CZ2格式字库的压缩算法始终不确定,CZ1的LZW不能用,最终我们决定将字库直接打包成CZ1格式,经过测试引擎也是可以正常读取的。

字库是9-21日DeQxJ00制作完成的,然后我用NS模拟器对NS版《Flowers》进行字体测试,不过可能是因为DeQxJ00找的不是等高字体…老是发生某个字显示不全的问题。

2020-10-1

国庆长假第一天,修复LucaSystemTools解包pak时的编码错误。

以及使用《Summer Pockets》PC汉化组提供的文本,开始移植汉化NS《Summer Pockets》,整理文本以及编写导入脚本。

因为LucaSystemTools提取的脚本文本是属于那种汇编形式的,指令、数据和文本都在一起,所以要用脚本将纯文本替换进提取出的脚本中,然后再使用LucaSystemTools进行导入即可。

2020-10-2

支持PSV《ISLAND》脚本的导出

正式加入根据脚本版本(如Ver2、Ver3)提取脚本,而不是以前的没加入一个游戏都需要加入一个case来区分,此时已知游戏的版本为:

  • Ver2 : PSVita《Flowers》系列、PSVita《ISLAND》
  • Ver3 : NS《Summer Pocket》、NS《Clannad》、NS《Tomoyo After Its a Wonderful Life CS Edition》、NS《Flowers - Shiki》等NS平台的LucaSystem引擎游戏。
  • Ver1则是因为脚本差异过大(psb),所以不合在一起。

2020-10-3

DeQxJ00做好了4bits CZ1图像的提取和制作工具。
PSV上的《ISLAND》也确定开始移植汉化,首先要处理文本。

2020-10-4

Commit

在测试《Summer Pockets》汉化时,发现了到选项时会乱跳,导致游戏崩溃,应该是修改后的脚本跳转出现了问题。

我一直以为这个脚本的跳转是按照行数跳转的,结果稍微研究了一下发现,IF、GOTO、JUMP等之类的指令,跳转地址是脚本文件的偏移地址(即某条指令的开头offset),这就很麻烦了,要根据文本的变动修改这些跳转点,而且要从导出文本就开始标记。

增加了一种Position类型的数据,实际为int32,主要是标记某些指令的跳转。

实现跳转主要是在解析脚本时,遇到Position类型的数据,就放入一个字典中储存起来,并加上一个唯一跳转标记。等脚本解析完毕后,再根据跳转字典中储存的位置信息,找到对应的语句,加上对应的跳转标记。

编译时也是同样的方法,先完整编译,遇到跳转标记,先用0填充,然后记录下跳转标记ID以及所在位置,编译完后再查表,将对应的偏移填到之前用0填充的地方。

经测试,跳转完美实现。

至于Ver2的脚本跳转,应该也是一样的,就是OPCODE需要进行修改。

至此,NS《Summer Pocket》文本移植完毕,剩下在程序中的系统菜单文本,以及少量变动文本暂时搁置,有时间在搞。

PS: 2021.4,仍然没有进行下一步= =

2020-10-5 ~ 2020-10-8

由于代码越来越臃肿,而且提取出的脚本中标记符号越来越多,先不说看起来很不舒服,导入文本那是真的麻烦,需要用Python二次处理提取的脚本,对于此工具来说根本就是本末倒置,都这样了为什么不直接去处理原脚本二进制呢?所以决定准备重构代码,以支持简单的汉化功能。

首先每条指令分四个部分(Ver3脚本):

  1. Length : 此条指令的长度,int16类型
  2. OPCODE : 操作指令,int8类型
  3. CodeInfo : 目前还是未知数据,猜测可能和参数数量有关,是由一个int8类型的count,和conut个int16数据组成(对于END指令来说是count-1个)
  4. Params : 参数列表

然后除了Length,其他部分都结构化的储存在CodeLine中,因为Length要根据指令长度进行变动,所以只在导入时需要用。CodeLine中除了储存这些原本就有的数据,还需要特别记录跳转点之类的随时会变动的数据,以在导入时使用。

这样就把脚本的所有数据都储存在数据结构中,导出的话是二进制->CodeLine[],然后CodeLine[]->文本,导入的话是文本->CodeLine[],然后CodeLine[]->二进制。其中二进制<->CodeLine[]过程很简单,只要按照脚本的读取顺序,将参数转为二进制即可,主要的部分还是和文本的转化。

数据结构转文本,最简单的办法当然是序列化为Json,稍加处理后,使用Newtonsoft.Json库完成了序列化与反序列化。

后面还增加了Ver2的支持,和Ver2有些许差别:

  1. OPCODE : int8类型
  2. Length : int8类型,为实际长度的一半,真正的脚本长度为Length*2
  3. CodeInfo : null
  4. Params : 与Ver3一样

除了反序列化,还增加了其他的文本格式。老的格式还是兼容的,毕竟一些游戏已经开始汉化了。新格式有两个,一个是lua格式,一个是luae格式。没错,就是lua脚本的那种格式,不过当然是不可执行的,毕竟没有解释器。

lua格式是可导入的格式,每个数据都有对应的类型标记,虽然是lua格式,但是没luae像lua,因为大量的类型标记符号很难阅读。
luae是纯导出格式,就是用来看的(说不定以后真的可以跑?),所以没有任何类型标记,和真正的lua脚本几乎是一样的,当然还是不能运行就是了。

期间DevSeed和DeQxJ00还整好了Github Action的自动发布功能

数次Commits:

2020-10-8 Version 0.2.0

LucaSystemTools_20201007(0.2.0)

0.1.0在2020-10-6发布,功能较少,不做记录

2020-10-12

修复了Jump跳转出现的问题

增加了一个控制台的ScriptOpcodeGuide,可以根据提示生成OPCODE,由于逻辑过于复杂,所以可能会坑掉

修改PSV《Flowers》的OPCODE,使其支持跳转指令

2020-10-12 Version 0.3.1

LucaSystemTools_20201012(0.3.1)

2020-10-13

修复Lua格式支持自定义编码表的功能,这样基本可以只使用此工具完成汉化

2020-10-13 Version 0.3.3

LucaSystemTools_20201012(v0.3.3)

2020-10-18

因为DevSeed好像打算把现有的PSV Flowers前三部(共四部)给汉化了,所以稍微处理了下OPCODE

新增了PSV《Flowers》第二部、第三部的OPCODE

2020-10-30 、2020-11-27 、2020-11-28

DeQxJ00增加了CZ0 24bit和32bit的支持,以及CZ0 32bit转8bit功能

2020-12-5

Commit

支持导出纯文本格式,具体格式仿造以前汉化组的格式,可以更方便的进行翻译工作。

开始准备加入一个WinForm的OpcodeGuide,因为目前的OPCODE都是我从IDA里取到的字符串,再加上凭借经验推测出的参数类型,为了能够让更多的人使用,准备做一个有界面的,引导推测Opcode参数类型的工具。

2020-12-5 ~ 2020-12-14

这段时间主要就是完成WinForm版OpcodeGuide,说起来容易做起来难。

先是能够暂停、动态的读取脚本,就需要修改原本的ScriptReader,以及增加一个OpcodeEntity类来储存和显示实时变动的指令行和OPCODE。

当然,最麻烦的还是WinForm的界面交互。

刚开始也不是没想过使用html5的方法,但是Electron对于C#的适配一般,虽然有Electron.NET,但是要用到ASP的知识,我本身是学javaweb的,.NET也仅限于控制台程序和WinForm,所以放弃了。用其他语言如js,与.NETCore的交互又有些麻烦,毕竟LucaSystemTools是.NETCore开发的,需要频繁的交互,所以也放弃了。

最终还是只能用WinForm,界面交互与设计也是硬着头皮上,不过还好最终完成了这个有(没)用的简(超)单(级)工(复)具(杂)…

来看下界面:
s1.png
s2.png

有一说一我不认为有人能够在不加引导的情况下使用它,还不如我自己去挨个试!

2020-12-14 Version 1.0.1

LucaSystemTools_20201214(v1.0.1)

2020-12-19 PSV《Flowers春》汉化完成

在边摸鱼边找人帮忙处理图片中,《Flowers春》终于做完了全部,完成了汉化。
汉化发布贴