GB/GBC汉化经验分享之十八--大字的输出程序 心得研究

六级用户 RangerMarsh 4天前 429

十八、大字的输出程序


这一部分将要分享使用4Tile显示一个汉字的方法。

主程序WriteLarge包括3个部分:WordLocation用于计算出所要显示的字符在字库中的位置;VRAMWrite将这个字符对应的4Tile写到VRAM中;MAPWrite将这些Tile写到MAP上从而可以在屏幕上显示对应的汉字。

10:4100

WriteLarge:

push  hl

push  de

push  bc

push  af

call WordLocation

call VRAMWrite

pop af

pop bc

pop de

pop hl

call MAPWrite

ret

 

程序WordLocation(10:4200)用于根据字符编码换算出该字符在Bank中的地址

10:4200

WordLocation:

ld c,a

ld a,0

ld b,a

sla c

rl b

sla c

rl b

sla c

rl b

sla c

rl b

ld   hl,4000

add  hl,bc

add  hl,bc

add  hl,bc

add  hl,bc

ret 

 

首先通过位运算把a值扩大10倍放到bc中,字库的起始地址是4000,累加4bc得到最终的地址,并把这个地址保存在hl中。需要注意的是对于不同的字库类型,计算字符地址时会有差别,这里是按照GB 2bpp的字体来写的程序。

接下来我们就需要把这些TileRom中读出来并写到VRAM中,通过下面这程序VRAMWrite来实现

10:4230

VRAMwrite:

push hl

call  VRAMaddr

pop hl

ld  b,40

ReadNext:

ld  a,(DA01)

sub a,20

call ReadTile

push af

judgeVRAM:

ld a,(FF00+41)

and a,03

cp a,00

jr nz,judgeVRAM

pop af

ld   (de),a

inc  de

dec  b

jr nz,ReadNext

ld a,d

ld (DA04),a

ld a,e

ld (DA05),a

ret 

 

首先调用程序VRAMaddr计算出VRAM中可写入的地址保存在de。接下来要读出字符的Tile的一个字节放到a,字符的Bank号根据双字节编码的第一个字节计算出来,这个值已经被保存在DA01中,取出这个值,减去20得到实际的Bank号。调用程序ReadTile读出Tile信息。由于VRAM不是随时可以写入的,需要先判断VRAM是否是可以写入的状态,具体原理我也不太明白,可以直接套用这里的程序。一旦判断出可以写入就执行写入操作,然后将de值增加1,再接着读出下一个字节来写入,重复40次,把一个字对应的4Tile都写入到VRAM中。写完之后把当前de中的地址保存在DA04DA05中,后面的字可以跟在这个地址之后去写入。

VRAMaddr程序是用来生成VRAM中可以写入的地址

10:4280

VRAMaddr:

ld hl,DA04

ldi a,(hl)

cp a,0

jr  nz,VRAMaddread

VRAMreset:

ld  a,A0

ldd  (hl),a

ld  a,90

ldi  (hl),a

VRAMaddread:

cp a,97

jr z,VRAMreset

ld d,a

ld e,(hl)

call VRAMTile

ret

 

之前我们已经分析出来,《圣剑传说》这个游戏的VRAM中可以用来写入字体Tile的地方还是挺大的,从90A09760这些原来存放日文Tile的位置都可以写入。VRAM中可写入的地址信息我们是保存在DA04DA05中的。程序先判断DA04是否写有地址,没有的话写初始地址90A0,再判断这个地址是否是97开头,也就是VRAM最下面一行,是的话也跳回开头设置为初始的地址90A0

需要注意的是,对于对话这样一直在动态变化的文本, VRAM中的地址循环利用不会有大问题。但是对于菜单栏、状态栏等一些文本,大部分字是不会变的,只有少部分字在变,这样把所有VRAM拿来循环利用就会出问题。这时候就需要考虑给每一部分文字设置单独的VRAM区域,这个后面遇到再展开说明。

在计算完VRAM地址后,又调用程序VRAMTile,它的作用是根据deVRAM地址,计算出对应的Tile编号信息并保存到DA07,供后面写到MAP上时调用。

10:4260

VRAMTile:

ld   a,d

swap a

and  a,F0

ld   b,a

ld   a,e

swap a

and  a,0F

add  b

ld (DA07),a

ret

 

这个Tile编号就是将来要写到MAP上用来显示文字的,比如当VRAM地址是90A0时,这个地址对应的Tile编号就是0A,也就说接下来0A开始连续的4Tile就是用来显示这一个汉字的。

做完这些准备工作就是要把字符的Tile从字库中读出来,这里用到了ReadTile这个程序,其实它就是前面我们用来读取文本的程序的一部分,只不过开头指定Bank号那里不一样,我们先计算出字库的Bank号,然后从程序的第二句开始开始调用

0:3F8B

ReadTile:

push hl

call 2A21

pop hl

ldi  a,(hl)

push af

push hl

call 2A30

pop hl

pop af

ret

 

这一系列程序运行完后,我们就可以看到第一个字对应的4Tile已经被写到了VRAM中。

18-01.png

接下来就是要让这个字在屏幕上显示,按照之前分析的,我们直接借用原来的程序,利用e的值来控制位置。程序MAPwrite(10:4400)负责把一个字符的4Tile写到MAP中。0:3897用于写上半部分,0:389D用于写下半部分,e1后写字的后半部分。文字的第一个Tile编号保存在DA07,开始导入字库时选择的是垂直重组,所以一个字的四个Tile是按照左上、左下、右上、右下存放在VRAM里的,写到MAP时也按照这个顺序来写。

10:4400

MAPwrite:

ld a,(DA07)

push af

call 3897

pop af

inc a

push af

call 389D

inc e

pop af

inc a

push af

call 3897

pop af

inc a

call 389D

dec b

ret

 

因为我们这里相当于一次写了原来的两个字,所以b要多减1e在运行中已经加了1,所以结尾就不用再加1了。

这样我们就实现了对话部分的文本修改和大字输出。

18-02.png


上一篇:GB/GBC汉化经验分享之十七--新的文本读取程序
下一篇:【求助】海淘的wiiu到货了,问题不少
最新回复 (3)
  • 四级用户 夏虫不可语冰 4天前
    0 2
    感谢技术分享
  • 三级用户 fantasista 3天前
    0 3
    太强了,干货满满
  • 三级用户 409354317 3天前
    0 4
    很想学啊
    • 老男人游戏网配套论坛
      5
        立即登录 立即注册
发新帖
本论坛禁止发布SWITCH和PS4相关资源,若有其他侵权内容,请致邮3360342659#qq.com(#替换成@)删除。