如何将一个开源游戏移植给一款32位微控制器
扫描二维码
随时随地手机看文章
随着微控制器性能增强,已经有可能用它们执行一些在90年代还需要PC处理能力的程序,而游戏领域的应用受这一进展影响很大。现在可以在某种移动应用(包含图形LCD和一个32位 ARM微控制器)中实现第一个PC上的3D游戏。本文将阐述如何将一个开源PC游戏的代码移植到一款有适当源文件结构的微控制器上。
在上世纪90年代,游戏开始在计算机世界中蔓延。我还记得第一次玩Wolfenstein 3D,那是第一款3D的PC射击游戏。它由IdSoftware于1992年开发,是Doom的前身。Wolfenstein 3D证明PC的图形能力已足以满足这种类型3D动画的开发。90年代很多十几岁的年青人都会记得Wolfenstein 3D,因为这是第一款把3D世界带到他们PC上的游戏。90年代中期它的源码在互联网上公开,现在还能找到。现在我想再玩这款游戏,但不是在我的PC上。我将利用一只微控制器的功率和集成度。
这里需要补充一句:本文并不打算分析Wolfenstein 3D的源码。很多文章已经做过这件事了。本文的目标是说明将复杂代码移植到新平台上的方法。不过,这款游戏的结构做得很好,解释一下还是很有意思的。事实上在1992年,Wolfenstein 3D在3D游戏领域是一场革命。它是第一款玩家能在3D场景中自由移动的游戏。
在此游戏中,图像与源码同等重要,因为它采用了大量贴图和子画面。这些都采用光线投射(Ray Casting)方法定位在屏幕上,从而给游戏以一种3D效果。光线投射包含了从一个POV(视点)的投射半径。并采用了一系列技巧以实现加速。例如,为了在像素点屏幕上投射一个半径,要做一个空间搜索,以找到该半径与最近墙上的交汇点。在Wolfenstein 3D中,墙面和贴图的尺寸都是64 x 64像素(见图3)。
虽然该游戏在当时取得了无比的成功,但它也有一些局限。其中之一是墙的高度全都一样,它们全是90°,没有斜角。这些限制减轻了移植的难度,因为它们代表着源码不太复杂。另一个限制是地面和天花板没有贴图。
我会尝试在一只较新的32位微控制器上给这款游戏以新的生命。一个必需的部件是建立一个控制游戏的应用电路板。从用户角度只有两个东西是可见的,一个240 x 320 TFT彩色屏幕,以及一组让玩家在Wolfenstein 3D迷宫中穿越的按键。另外,微控制器用于屏幕和按键管理。由于这种类型屏幕采用一种并行接口(16位宽),需要选择一种能够驱动这种屏幕的微控制器。
如何更顺利地移植源码?
Wolfenstein 3D的源码相当复杂。源码越复杂,控制它就越难。因此,将这个应用移植到一个新的目标上非常困难。在开始以前,重要的是了解用于编写原应用的语言是否为可移植的,而且该语言的的编译器是否能用于新的目标。Wolfenstein 3D采用C语言编写。C语言有利于移植,因为它在微控制器领域广泛可用,市场上现有很多编译器与调试器。
C语言允许一个源码对多个目标,前提是它采用一种逻辑和清楚的方式编写。项目源文件的组织是一个考虑因素。图4提出了一种方法。
图示的软件方法将原始源码与应用板使用的物理层分隔开来。移植过程中,原始游戏的源码必须作少许修改,用到硬件的函数必须转移(并修改)到“可移植”段。
当你准备将一个程序移植到一个新的目标时,主要问题是“哪种新目标机能够执行这个程序?”要理解这个需求,就需要知道源码的主要功能,如外设的类型和数量,以及内存的大小(Wolfenstein 3D需要至少500KB程序空间和96KB RAM空间)。
应用的核心必须是一只32位微控制器,因为Wolfenstein 3D的执行要求高性能的算术计算,用于光线投射方法和刷新屏幕的执行速度,8位或16位微控制器无法达到这种性能水平。另外,为了简化电路板布局,需要选择一款嵌入了程序内存(闪存)的微控制器。现在,市场上存在着大量这类32位微控制器,但ARM处理器是嵌入式应用的标准处理器。
我选择的是意法半导体公司的STM32,因为它采用了一个ARM Cortex-M3核心,专为嵌入式应用而开发。请允许我介绍这个STM32 32bit闪存微控制器系列,尤其是STM32F103ZE产品。
STM32F103ZE运行频率最高可达72MHz,应用电源为2.0V至3.6V。它提供512KB闪存和64KB RAM。外存控制(灵活的静态内存控制,FSMC)可使STM32F10xxx微控制器与各种存储器接口(SRAM、NOR闪存...)。FSMC有16根数据线和26根地址线,可用五根独立的片选脚,最多连接64MB内存。在Wolfenstein 3D应用板上,这个接口用于驱动TFT显示器和外接的4MB SRAM高速异步内存。键盘由通用IO直接驱动。应用板为3V工作,采用3只1.2V电池与一只LM317可调稳压器的组合。
意法半导体提供一个非常有用的软件库,它包含很多STM32功能管理实例。在这次移植中,软件库用于编写TFT显示器硬件的驱动。图5表示架构需要的项目,Wolfenstein 3D文件夹包含两个子文件夹。
Appli文件夹包含IDE项目以及硬件驱动源码,如TFT屏幕。该文件夹包含硬件应用板的说明(在我们这里是STM3210E-EVAL),它还包含了STM32库,用于管理电路板硬件和IDE项目。Wolfenstein 3D的源码用库函数作硬件驱动。
“source”文件夹包含了Wolfenstein 3D的原始源码,源码中所有指令或函数都不与应用板硬件直接交互,子文件夹“portable”包括用于在游戏原始代码与代码执行目标硬件之间建立连接的函数。在我们这种情况下,我们还有一个子文件夹STM3210E-EVAL,这个文件夹包含调用应用板硬件的函数。
让我们看一下显示管理的例子。Wolfenstein 3D源码包含一个VW_UpdateScreen函数,这个函数根据内部视频缓冲的内容刷新TFT屏幕,于是需要驱动TFT屏幕。因此,它必须在文件夹“portable/STM3210E-EVAL”中定义。VW_UpdateScreen函数会调用在文件夹“appli/ STM3210E-EVAL”中定义的基本函数(驱动)。
文件夹“source/portable/STM3210E-EVAL/”包含与编译器兼容的类型说明与定义。通过这种方法处理,就能够将一个目标的源码移植到另一个目标,而无需修改复杂的源文件。举个有用的例子,源码要转换到一个不同映射的STM32应用,它有不同的接口硬件,或编译器有改变。这时只需要为新的目标更新“appli/STM3210E-EVAL/”和“source/portable/STM3210E-EVAL/”文件夹中的约束文件。结果在图6中。它看似90年代的一款口袋机游戏。[!--empirenews.page--]
采用C编写的老式PC游戏的源码现在仍能从互联网上获得。多亏有微控制器的强大性能和LCD显示器的集成,我们现在还能体验到这些游戏。
Captions:
图1. 应用板上的Wolfentien 3D。
图2. 光线投射模型。
图3. 纹理与sprite(Texture and sprite)。
图4. 软件架构。
图5. 文件夹的项目结构。
图6. 最终应用。