认识Gameboy掌机的文字和字库

  • 认识Gameboy掌机的文字和字库
    文/神奇误差


    Gameboy 和 Gameboy Color(GB/GBC) 的画面显示是基于画片(Tile)的,文字也不例外。在使用现代计算机时,我们可能经常听说,字体,编码格式,UTF-8,字库等等等等关于文字的术语。与GB/GBC 打交道时,拜其简单硬件以及与底层硬件的紧密联系所赐,Gameboy掌机的文字和字库显得通俗易懂多了。
    画片



    玩GB/GBC 游戏甚至更早期的8位机(红白机,小霸王)时,我们可能会注意到一幅画面中经常会有重复的部分,而且游戏画面似乎以方块为基础。事实上,一幅画面确实是以一个个画片拼接而成。以GB/GBC 为例,一个画片的尺寸为8*8像素,或者8*16像素。GB/GBC 的屏幕分辨率160*144,长度方向160像素,宽度方向144 像素。以8*8像素的画片为例,那么在长度方向(横向),可以容纳20个画片,宽度方向(纵向)可以容纳18个画片。


    文字
    GB/GBC 的游戏中,绝大部分的日文字符(有的浊音清音分开显示)和英文字符,都是一个字符占用一个画片。
    游戏画面的显示方式
    我们看到的游戏画面其实都是静止的。由于人类视觉存在暂留现象,当一幅幅相互有关联的图画快速在眼前播放时,似乎就看到了运动的画面。GB/GBC掌机一秒钟约显示60幅图画,也即一秒钟有60帧图画。
    前文提到GB/GBC 的图像都是基于画片的,那么一个个小画片是如何组合成为一个完整的屏幕的呢?这里涉及两个概念,画片和画片映射表。
    举一个简单的例子,班级要重新安排座位,而全班每一个学生都有学号,一张桌子坐两个人。班主任这次决定换一个方式安排座位。她先把教室清空,把学生们都请出教室,然后一个人默默地在每一张桌子上放两个人的学号,安排完毕后,学生们按照学号入座,于是新的座位表就形成了。班主任站在讲台上,于是就看见了一幅新的图像。班主任自己编了一个座位安排表小册子,一个月重排一次座位,让学生们按照学号入座。于是每个月,这个班级看起来都不太一样。如果班主任足够疯狂,学生们足够闪电,1分钟安排60次座位,那么这个班级的人就。。。全疯了。
    GB/GBC 掌机显示图像时,画片相当于一个个学生,画片映射表相当于那个座位安排表,画片根据映射表的指示,组成一块屏幕图案。当画片映射表发生变化时,画片重新找到自己的位置,屏幕图案发生变化。
    文字的显示方式
    前文提到,一个字符也是一个画片。为了显示恰当的文字,也存在这样的座位安排表,我们叫它文本,而显示字符的画片就是一个个文字。
    举例来说,现在有一些画片,他们显示了字符‘你(01)’,’晨(02)’,‘早(03)’,‘好(04)’。那么如果要在屏幕上显示“你好”这两个字,那么需要就告诉掌机,请显示 01 04 字符,如果要在屏幕上显示“早晨好”,那么就需要告诉掌机请显示 03 02 04 字符。
    显示文本流程
    对于文字量大的游戏,一般有一个专门的地方储存文本(文字),如前文提到的 01 04, 03 02 04 会储存在专门的地方。而字库画片会储存在另一个位置。使用时,掌机按照文本的指示(座位安排表),按照编号(学号),从专门储存字库画片的地方读取相应的文字,并显示在屏幕上。
    字库的储存
    如前文所述,大部分字库的一个字符都是占用一个8*8的画片。我们知道,计算机储存数据的方式就是0和1。如果规定1代表有颜色,0代表没有颜色,那么下图这个巨型的字母O第一行可以表示为 00111100。为了记忆方便,一般用16进制表示,高四位(最左边的四位)是0011,它们代表16进制的3,为了区分,经常给16进制数字后面加字母H,代表HEX16进制。因此0011也可写作3H。低四位(最右边的四位)是1100它们代表16进制的CH。那么合起来,这个巨型的字母O第一行写成16进制就是3CH(注意,此处的H是为了表示这是16进制计数方式)



    其它字母以此类推。然而GB/GBC 是4阶色彩显示屏。如GB掌机,就可以显示黑色,深灰,浅灰,白色四种颜色。因此有时程序中存储这样的字母O可能并不是 3C 42 81 81 81 81 42 3C 这样的一字排开,而是3C FF 42 FF 81 FF 81 FF 81 FF 81 FF 42 FF 3C FF或者3C 00 42 00 81 00 81 00 81 00 81 00 42 00 3C 00这样储存。甚至是 3C 3C 42 42 81 81 81 81 81 81 81 81 42 42 3C 3C。


    寻找GB\GBC游戏中字库的入口地址
    (以《幸存少年:逃出!双子岛》(孤岛冒险2)为例)
    如前文所述,游戏中的文字分为两部分,文本和字库。文本是一串串字符的代号(代号也可称为编码方式),游戏程序根据这一串串代号从字库中提取出来对应的文字显示在屏幕上(还记得丧心病狂班主任一分钟安排60次座位的故事么?)。
    文本的寻找需要一定的技巧,适合另开文来说,字库入口倒是简单的很,在此简单提要。
    你至少需要一款工具,GB/GBC 的模拟器,BGB。最好,还有一个16进制的文本编辑器,比如WinHex。
    打开Debugger和Vram Viewer,在Tile 栏将鼠标指向第一个日文字符,你可以清楚地看到它的显存地址是8E90




    然后在Debugger中下方的内存查看栏中,找到8E90地址,右键Copy, 复制16个字节出来,得到
    000004047F7F04041C1C24241C1C0404


    这16个字节除去表示灰度的8个字节,是怎么表示文字的呢



    在WinHex中查找16进制数据,注意不是查找ASCII字符,在地址0x80780 中找到(80780是16进制数据)




    实际上,这就是储存字库的地方。一般来说,字库都会整齐地码放在软件中。有兴趣翻翻看,其实地址0x80000就是字库的入口地址


    0x80000 开始的地方储存了这个游戏的字库,如果全部提取出来,它们就是这样的。


    一行16个字符,很多行。
    调用第5行,第6个字符,就写作56H。当然,软件设计中,可能不会写作56H可能还要加上偏移等等数据。比如,可能全部字符的代码全部减1,5行6列的字符,它的编码是55H而不是56H。
    使用时,按照不同的编号,顺序调用就行了。(还记的那个丧心病狂的班主任手里的座位安排表么?)


    附件里是 BGB Gameboyr 模拟器。
    它的官网是http://bgb.bircd.org/

Join us

Have your own thoughts on this discussion? Wanna help others, avoid the mistakes you met before? Wanna contribute more to this or other topic? Just join us! Registration is free. Join us!