elona吧 关注:67,968贴子:1,093,200

HSP汉化教程

只看楼主收藏回复

介绍一些在汉化HSP软件时可能会遇到的问题,以及几种解决方法。
实际上在汉化中遇到的问题,技术方面只会占较小的一部分,
所以本贴偏科普性质,也请带有轻松愉快的心情阅读本贴。
还有需要注明的是,我只是一个普通的ELONA爱好者,对现在使用的汉化版并没有什么贡献。


1楼2018-07-23 12:55回复
    1·HSP是什么?
    HSP是一种来自日本的编程语言,全称hot soup processor。而ELONA就是用HSP制作的。
    HSP并不会直接编译到机器语言,而是像Java一样编译到字节码,然后由虚拟机解释执行。
    HSP现已支持包括Windows,IOS,安卓等多种平台,但是并不通用。
    HSP的Windows版是使用C++制作的,并且是开源的。
    链接
    官网:hsp.tv
    源码下载:dev.onionsoft.net/trac/openhsp


    2楼2018-07-23 13:04
    回复
      2·1 编码的问题
      HSP初期只支持shiftjis编码,这是一种日文编码。在后来又加入了对utf的支持。
      因为shiftjis编码中的汉字有限,并不能满足汉化的需求,所以需要使用其他编码。
      2·1·1 gbk编码
      gbk是一种中文编码,不过其实也包含日文中的假名,以及一些日本汉字。
      所以用来汉化是没有问题的,而问题在于HSP并没有对gbk的支持。
      所以,如果选择使用gbk的话,就需要一些方法来在HSP中使用gbk。
      2.1.2 utf编码
      使用utf的优势有丰富的字符,以及HSP的原生支持。
      而问题在于ELONA存在着基于shiftjis的代码,而shiftjis和utf的差距与相对来说是比较大的,
      所以,如果选择使用utf的话,就需要对ELONA代码做一些修改。


      3楼2018-07-23 13:14
      回复
        2.2 编译的问题
        因为我只使用gbk对ELONA进行过汉化,所以本文之后也是更多的基于gbk而非utf。
        虽说gbk与shiftjis比较相似,但是还有有一点点差别的,问题出在shiftjis中的半角假名。
        在gbk中低于128的字符是单字节,而高于128的字符为双字节。
        而在shiftjis中除了低于128的部分,介于160与223以及大于253的部分,也是单字节。
        所以,在直接使用shiftjis的规则对待gbk字符串时,会遇到一些诡异的问题。
        比如说,如果在不转码的情况下运行,mes "足"; (意思是输出 足 )时,输出的不是 足 而是 足"; ,
        这是因为"足";的gbk编码是 34 215 227 34 59,程序读取到第一个34(双引号)时,判断这是一个字符串,
        然后读到215,因为在shiftjis中这是单字节的,所以程序继续读227,程序认为他是双字节,
        于是下一个34,字符串结束的双引号被略过了。而HSP中双引号是可以不匹配的,程序会一直读到换行。
        所以,最后输出的不是 足 而是 足";,对于这样的简单语句来说,只是输出错误,
        而对于复杂如ELONA的代码来说,会根本无法编译。
        2.2.1 读取外部文本
        既然gbk在代码中会无法编译,那么将文本放到外部的txt中,由程序在运行时读取,是不是就可以解决问题呢?
        答案是肯定的,这样做会稍微麻烦一些,但是在安全性方面会有特别的优势,这点放到下面。
        2.2.2 修改HSP编译器
        既然编译器认为文本是shiftjis,那么如果修改编译器,使其支持gbk,是不是就可以解决问题呢?
        答案也是肯定的,只讲目光聚集在编译期的话,这个方法可以说是完美无缺,也是很自然的一个方法。


        4楼2018-07-23 13:40
        回复
          不懂


          IP属地:广东来自Android客户端5楼2018-07-23 13:51
          回复
            2.3 虚拟机的问题
            如果已经解决了上面的问题,那么我们已经可以得到一份中文的程序了。
            但是,在这个时候我们会遇到另一些诡异的问题。比如说,人物没有肢体。
            这是为什么呢?
            因为在ELONA中,肢体存储为这样的格式"手|手|足|足",然后根据|拆分得到各个肢体的名字。
            你可能已经发现了,虚拟机也认为文本是shiftjis,所以并不能正确的拆分、处理字符串。
            2.3.1 修改虚拟机
            得益于HSP的开源,我们很轻松就可以对虚拟机动手脚,而这也应该是最自然的方法了吧。
            2.3.2 其他一些方法
            如果说你对于C++不是很熟悉(虽然实际上支持gbk的程度的话并不是很复杂的事情),
            那么还有一些相对来说简单一些的方法。我虽然也使用过这样的方法,但是如果可以的话,推荐修改虚拟机。
            比如说在文本中添加适当的空格以正确拆分文本,然后将空格去掉。
            再比如说使用自定义的函数替换基于shiftjis的原生函数等等。


            6楼2018-07-23 13:51
            回复
              2.4 ELONA的问题
              如果编译器,虚拟机的问题都解决了的话,那么得到的汉化基本上可以说是能玩的程度了。
              但问题还是接踵而至,比如说 换行乱码。
              实际上不论是编译器还是虚拟机的问题,本质上都是shiftjis中额外的单字节。
              换行乱码也是如此,如果选择gbk的话,这一步只要修改几处判定就可以完成了。
              而如果utf的话,问题会稍微偏多,我没有排查过,所以这里就略过了。


              7楼2018-07-23 13:55
              回复
                2.5 反编译的问题
                全数解决之后,这时汉化版在显示文本方面已经没什么问题了。
                正当心情愉悦,准备好好玩耍时,就会发现另外一些棘手的问题。
                比如说,制作料理崩溃,道具没有CD等等。
                而通过不断的排查,你会发现,这不是汉化的问题。
                即使是直接反编译后再编译的程序,也会存在这样的bug。
                那么答案已经非常明显了,是因为反编译程序本身存在的bug导致了这些bug。
                2.5.1 修!
                有bug的话,就修咯。很粗暴,也很有效的方法。
                而问题在于这样做如果没有自动化工具的话,会比较繁琐。
                2.5.2 让别人修
                如果你对ELONA比较熟悉的话,那么会知道存在着一个mod叫做custom,
                直接基于custom汉化的话,修复反编译bug的工作就不需要自己来做了。
                2.5.3 修改反编译软件
                如果说有什么彻底的方法的话,那么修改反编译程序可以算是一个,
                而这样做最大的问题是需要对C++以及HSP文件格式有一定了解,是有一定难度的。


                8楼2018-07-23 14:06
                回复
                  我歇会(
                  申个精(
                  @浮士德海风


                  来自iPhone客户端9楼2018-07-23 14:13
                  收起回复
                    妖怪农教又在整大计划了(


                    IP属地:福建10楼2018-07-23 15:49
                    回复


                      IP属地:福建11楼2018-07-23 15:49
                      回复
                        3·绕过反编译
                        如果对Java有一定了解的话,那么会知道在.class文件中存在着一个常量池记录着字符串等信息。
                        通过修改字符串常量池毫无疑问是可以汉化程序的,那么在HSP中存在着同样的结构吗?
                        答案是存在的。而且与Java相比,HSP的文件结构非常简单,
                        而且没有通过常量池的复用机制,常量折叠等,常量表与代码中字符串是一一对应的,
                        这样的基础使我们可以越过反编译,直接对常量池进行修改,从而实现汉化。
                        3·1 HSP的常量表
                        HSP文件的常量池非常的简单,将.ax(也就是HSP的字节码)文件加载到内存之后,
                        取得常量表起始位置的指针后,根据指针和偏移得到字符串。
                        举例来说,对于如下代码来说,
                        mes "abcd";mes "efg";
                        在.ax中会有如下字符串常量表
                        abcd\0efg\0
                        然后程序使用偏移0 + 地址 得到字符a的地址,进而得到字符串abcd并输出,
                        根据偏移5 + 地址 得到字符e的地址,进而得到字符串efg并输出。
                        那么修改虚拟机使其加载外部文件dcba\0gfe\0,并相应修改指针,就可以使输出变为dcba,gfe。
                        3·2 偏移的映射
                        但是只是修改常量表会带来一个问题,那就是如果修改前后的字符串长度不一致,
                        其后的所有常量都会错位,而不论是错位还是强制长度统一都是无法接受的。
                        我们可以通过建立一个 旧偏移-新偏移 的映射,从而解决这个问题。
                        3·3 优点与缺点
                        因为绕过了反编译和编译的步骤,所以不存在因反编译而产生的bug。
                        于此同时,因为可以从.ax提取文本、将文本直接转化为常量表,
                        所以从代码中提取文本、将翻译替换回代码的步骤是不必要的。
                        但是,因为没有反编译的步骤,所以几乎不能对已有代码做出什么修改。


                        13楼2018-07-23 18:46
                        回复
                          我写完了(
                          再申精(
                          @浮士德海风
                          @天发擦


                          16楼2018-07-23 19:19
                          回复
                            感谢教程
                            正因有授人以渔才可有鱼
                            感谢楼主 感谢所有像楼主这样的不藏私愿意耗费宝贵时间写教程的人


                            IP属地:河南来自Android客户端17楼2018-07-23 19:38
                            回复
                              棒棒!


                              IP属地:上海来自Android客户端18楼2018-07-23 19:38
                              回复