上了年纪的人一定记得在最古老的IBMPC上玩的两款经典游戏:挖金子和吃豆子。这些游戏可真是经典啊,当时小心翼翼地将它放在5寸软盘上溜进实验室,趁老师不在,调出来玩一下,一边逃避着怪物的追捕,一边眼观六路耳听八方防老师近来,其紧张与刺激带来的快感是现在舒舒服服地在家里打着画面华丽的游戏所不能比的。
在FPGA上跑通8086核以后,第一步想到的就是把挖金子和吃豆子移植上去跑通。
说干就干。
先确定关键词,经过几次google之后,确定吃豆子的英文叫pacman
上wiki上查一下,http://en.wikipedia.org/wiki/Pac-Man, 历史悠久啊,1979年就开始了, 英文看起来不方便,还是中文的吧http://zh.wikipedia.org/wiki/Pac-Man,不过中文版的信息少得可怜。从上面知道2006年12月才被移植到iPod上。看来,俺们这个project 还是满时髦的嘛。
下载了一个pacman.com, 十多K. 交给Winston研究。不久,Winston告诉我一个坏消息,pacman.com 里面用了很多Int10, Int1a 之类的中断,而我们的8086核现在还不支持中断向量表呢!
看来,直接走二进制兼容是行不通滴,就算支持了中断向量表,BIOS内部的代码也要写。工作量太大。
看来,只有自己写一个完全没有系统调用和BIOS调用的PACMAN代码了。
先看看有没有源代码可抄。
到sourceforge 和Debian 找了一下,果然有,但是都是基于 X的, 代码太多,剪裁起来太麻烦。继续寻找。找到一个java版的源代码,呵呵,从java 移植到C也挺累. …….. 功夫不负有心人,终于找到了一个大学的人工智能课程上的字符界面的pacman的源代码。Google 的搜索嘛,就是google: pacman.c site:edu
http://www.cc.gatech.edu/classes/cs3361_97_spring/pacman/pacman.c
装上Cygwin 编译pacman.c,编译器提示找不到libcurse之类的。呵呵,这个毛病常见,在Cygwin中装上libcurse就可以了。
又是一大堆编译错误。看来不止是一个文件啊。看代码,加上google, 终于找全了文件,可以在Cygwin下编译和玩了。界面很丑陋,是字符的,但一共才400行的程序改起来就太容易了。
下一步是编译成8086的16位程序。
这一步费了很多功夫,原因是俺熟悉的gnu tool Chain 不支持8086 16位程序!有个别人声称它可以做,需要打一堆补丁。
最后,决定用TurboC2.0来做。
经过数个小时的奋战,终于可以在TurboC2.0 下用字符界面跑起来了。
下一步是编译成8086的16位嵌入式程序。
虽然8086 16位程序和8086的16位嵌入式只有3字之差,但实现难度可不是一个数量级的,其根本原因在于TurboC2.0 太不灵活,很多必须自己控制的东东它都做成确省的。比如启动代码, c0.asm。终于明白了当年华为做交换机时为什么用怪怪的HIGHC而不是TurboC了。
修改c0.asm是一个痛苦的过程,很多小时都没有成功。
再上google, 换关键词搜,搜到了救命恩人Bob Haas 写的WRITING ROMABLE CODE IN TURBO C。 下载它提供的romize工具。这个工具解决了TurborC没有GNU链接时的ldscript功能的问题。 编译romize后,无法正确链接,郁闷5分钟后, 修改romize源代码一小处, 通过。
这时,一个可以不需要依赖任何库和BIOS的纯嵌入式rom版的pacman就制造出来了。文件是rom.bin
用8086比较cool的是这rom.bin 可以在dos窗口下直接用debug 调,非常方便,这比arm之类的交叉编译强多了。
下一步是生成PC仿真调试环境。
每一句话都用汇编,并要写成rom下载到fpga上调试,显然是效率很低滴,只适合最底层的代码。因此,用简单的条件编译,就可以让绝大部分代码的调试在PC上完成。在这个环境下,图形化的pacman就搞定了。
下面,就是在FPGA上调图形控制器了。Michael Ye 写的Spartan3E上的图形控制器和PC上的排列格式有所不同,因此需要调以下。
至此,在8086上跑吃豆子游戏的嵌入式软件部分工作告一段落。