SJIS编码与对应的 PS BIOS 字库偏移的换算
文/Agemo
2003-09-24
在PS syscall 专门对应函数是 Krom2RawAdd() 即 $B0 call $51
入口 a0 = SJIS代码
出口 v0 = BIOS中对应字模的内存开始地址,自然以 $bfc...开头
如果一个游戏使用了BIOS字库,则一定有代码调用Krom2RawAdd()
Krom2RawAdd 的实际执行过程是一个查表+计算的过程。因为PS BIOS只取了SJIS
编码的一部分,所以不连续。前面的标点区没规律,后面的汉字区可以不用查表直接
用公式计算的。我也查过SJIS一级字库的区域划分方法,不过与PS实际所采用的有
不少出入(也可能是我没查对资料)。
看了这个函数的汇编,改了一个C代码等价程序: SJIS.cpp
题外话,略微题一下syscall的主要执行过程
在BIOS文件偏移$10000处对应syscall一级跳转表(对应 a0,b0,c0,d0)
syscall的几乎所有代码在PS启动后会复制到内存地址前0x10000以内。
Krom2RawAdd = $B0 call $51, 调用方法一般这么写:
addiu t2, zero, 0xb0
jr t2
addiu t1, zero, 0x51
以下从内存中反编译,而不是BIOS.
我们要找的是 $B0.
000000b0 : lui t0, 0
000000b4 : addiu t0, t0, 0x05e0
000000b8 : jr t0
000000bc : nop
这是查子功能函数跳转表, t1 入口参数子功能号,跳转地址 = 0x00000874 + 4*t1
000005e0 : lui t0, 0
000005e4 : addiu t0, t0, 0x0874
000005e8 : sll t1, t1, 2
000005ec : add t0, t0, t1
000005f0 : lw t0, 0000(t0)
000005f4 : nop
000005f8 : jr t0
000005fc : nop
下面就是 Krom2RawAdd() 函数体了
000065e0 : andi a0, a0, 0xffff
...........
...........
后记:
一般汉化是不需要研究这个算法的,直接改掉以前的字库定位代码就行。
弄这个主要是因为在xade的月下汉化补丁基础上,继续做不依赖BIOS字库的补丁的需要。
不依赖BIOS字库的原理很简单,把字库读入内存,同时要修改相应的字库定位部分代码。
唯一难点在于内存是否够。如果内存不够,其他解决办法(如分段加载字库)就麻烦了。
内存不够也是非ROM类汉化(如PS)字库扩容的主要难点。非常幸运的是,月下程序的有
一些空闲的内存区域,加上月下字模少,只有1700左右。(我见过的其他游戏内存都塞的
很满的样子,月下这么好,省事多了)
至于文字的SJIS编码方式我没法改动(因为当时是独立做的),所以就需要这个算法了。
但是但是并没研究这个算法,只是调用 Krom2RawAdd()后再减去一个数字就得到现在的
字库偏移,反正字顺序是一样的。
但是后来发现在PS机上运行有BUG,一时找不到原因,就自己重新跟踪研究了一下这个算法
现在月下的SJIS定位字库算法都是自己写的,没有借用Krom2RawAdd()。
这个研究是很久以前做的,最近整理写出来。
|