PSP 编程导学(二)

第二课
创建你的第一个程序
一篇在Sony PSP上安装,创建并执行简单的"Hello World"应用程序的攻略


读完第一课之后,你已经拥有一个可工作的开发环境,并可以在其中创建你的应用程序了。现在该做什么呢?好,下面就是你期待已久的部分了——你的第一个PSP程序。这篇导学将介绍C语言的基本知识和你将要构造的程序的基础。

我们先要创建一个目录结构来组织我们的工程。打开一个CYGWIN bash shell,输入"mkdir projects"并回车。这个"mkdir"命令代表"make directory"(创建目录),它将在你当前的操作路径下创建一个目录或文件夹。那么现在我们为所有的工程建立了一个新文件夹,进入这个文件夹,通过"cd projects"命令。现在我们为这个具体的工程建立另一个目录。输入"mkdir helloworld"并回车。现在通过"cd helloworld"切换到新目录中。

下一步是打开一个文本编辑器。你使用什么并不真正重要,可以是记事本、写字板,无论什么都行。我喜欢用一个专门来编辑C/C++源代码的编辑器,因为它们有语法高亮显示的功能(我用Dev-C++),但是说实话,用什么都无关紧要,只要你知道如何去使用它。

现在,在"helloworld"路经下创建一个叫"main.c"的文件。这将包括我们程序的源代码。对那些不知道什么是源代码的人(我知道会有一些的)我要解释一下,源代码是我们创建程序时所写的东西。它是以一种人们能够理解的方式写成的。在大多数语言中,源代码需要被转换成计算机(我们这里是PSP)能够理解的格式。这叫做编译语言,C和C++都属于这类语言(这个转换过程可以通过我们在第一课中建立的编译器来进行)。还有一些其它的编程语言,他们利用一种叫做解释器的东西来解释源代码,并同时发送出机器代码。这叫做脚本语言(比如PHP就是一种脚本语言)。

好,那么我们已经有了一个新文件来放置我们的源代码。现在我们该开始写了。程序第一部分应该包含一些注释,来说明程序的目的、创建时间、作者。注释是一些不被编译进二进制文件的代码行(或被脚本语言的解释器忽略的代码行)。注释是代码的重要部分,因为一段时间后当你或者其他人回来修改你的代码的时候,你可能不记得这些错综复杂的程序到底干了些什么。所以,你可以以注释的形式给自己留下一些提示。注释是通过"//"和"/*"表明的。当你看到"//"的时候,他表示该行剩下的部分是注释。"/*"表示编译器(或解释器)开始忽略代码直到遇到一个"*/"操作符。通过"/*"操作符标明的注释可以跨越多行,但是用"//"标明的注释只能注释掉那行余下的部分。

所以,在开始写我们的程序的时候,我们在最上边写下如下注释,包括它做了些什么,何时创建,还有是谁写的。
// Hello World - My First App for the PSP

/*
          This program was created by (Your Name Here) on (Date Here)
          It is a simple "Hello World" Application.
*/
在程序的下一部分,我们告诉编译器我们将在程序中用到那些头文件和包含文件。从本质上来说"#include"指令所做的就是把你传给它的文件中的代码复制到你的程序中。这使你的程序保持简单,同时还能利用那些已经为你写好了的高级代码。include指令即可以包含编译器自带的头文件(或者你添加到编译器的),又可以包括特定项目的特定头文件。分辨include的是上述的哪一种文件的方法是看后面的文件是放在"<>"之中还是放在引号之中的。用小于号大于号include的文件是编译器包含("include")的路径中的文件,用引号include的文件是与当前文件相同路径下的文件。我们要在我们的程序中包含两个文件。第一个是"pspkernel.h"。这是一个你写所有PSP简单程序都应该include的文件。它包含了所有专门用于你的PSP的代码。如果你没有include这个文件,你的程序将不能够在PSP上运行。第二个文件我们要 include的是"pspdebug.h"。这个文件包含了一些对调试程序很有用的函数,明确地说它包括了我们用来向屏幕显示文本信息的函数。所以,添加如下代码到你的程序中:
#include <pspkernel.h>
#include <pspdebug.h>
下一步我们告诉PSP一点关于程序的东西。这其实不那么重要,没有它你的程序也可以通过编译,但是保留它常常会是个好主意(如果仅仅为了向前兼容)。第一个属性是程序的名字,但是它绝不是程序将显示的名字(我们将在以后改变程序显示的名字)。其他的值是其他的属性(留着不用管),主版本号、副版本号。除了名字我们让所有这些都保留默认的就行了。所以,添加如下这行代码到你的程序中:
PSP_MODULE_INFO("Hello World", 0, 1, 1);
现在我们写一个用来向屏幕写信息的函数。这步是可选的,但是它使编写基于文本的程序轻松了很多。这行代码本质上是把PSP内建的函数"pspDebugScreenPrintf"改变成更容易输入的(名字比较短的)函数。这个函数被用来向屏幕写信息(不久我们就会看到)。其实我们要做的就是把"pspDebugScreenPrintf"重命名为"printf"。所以,从现在开始每次我们用到"printf"时,编译器都将认为我们输入的是"pspDebugScreenPrintf"。这就是我们要做的;我们把"printf"定义成"pspDebugScreenPrintf",像这样:
#define printf pspDebugScreenPrintf
Ok,我现在有一个坏消息和一个好消息。坏消息是,下一块代码相当复杂。好消息是,你不需要理解它。这里只对它所做的事进行一下简单的解释(我们以后会一行一行地进行语法解释)。本质上说,这块代码所包括的是我们程序将要调用的函数。这些函数将使你的程序运行在PSP上并使你不用担心PSP会死机或意外退出游戏。将这段代码放入你的程序中:
/* Exit callback */
int exit_callback(int arg1, int arg2, void *common) {
          sceKernelExitGame();
          return 0;
}

/* Callback thread */
int CallbackThread(SceSize args, void *argp) {
          int cbid;

          cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
          sceKernelRegisterExitCallback(cbid);

          sceKernelSleepThreadCB();

          return 0;
}

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void) {
          int thid = 0;

          thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
          if(thid >= 0) {
                    sceKernelStartThread(thid, 0, 0);
          }

          return thid;
}
下一步,我们将定义"main"函数。每个C和C++程序都需要一个main函数。这是代码执行的开始位置。C(和一些C++)按顺序的形式运行的。这意味着代码走的是直线路径。比如如果你有如下的代码:
//不要把这些加到你的程序中
//它是一个例子

int myFunction() {
          //Print Out 'A'
          return 0;
}
int main() {
          //Print Out 'B'
          myFunction();
          //Print Out 'C'
          return 0;
}
注释(如果你忘了说明是注释,请看上文)的地方做它所描述的事情。程序将输出‘B'再输出’A'再输出‘C',因为编译器从main函数中开始。它先输出’B'然后它看到了对"myFunction"的调用(在上面定义的一个函数),走到那里,发现需要输出‘A'并且返回它(在main中)离开的地方,然后输出’C'。你的所有程序(除非你使用高级的C++编程)都会遵循这个线形的结构。所以,"main"函数对你的程序来说是至关重要的。要定义一个函数,你要使用如下的结构:"[return type] [function name]() {"。返回类型是指函数返回给程序的是什么。对"main"来说,返回类型总是"int"(代表整型)。函数名是指你函数的名字,"main"函数的名字很显然就是"main"。所以,把下边一行添加到你的代码中,来定义你的函数:
int main() {
现在我们需要添加两行代码来创建屏幕,并且使我们在之前定义的一些函数能够被使用(你不需要知道这两行代码是如何工作的)。甚至你不需要知道那些函数是如何工作的,重要的是掌握如何调用函数的概念。它实际上非常简单。你只需要写出函数名并在后面加上括号(如果有参数的话,将参数放在括号中,我们以后要讲到)。每行程序要以分号结尾。这是因为编译器看不到任何空白。两行代码之间,你可以空100行,编译器并不关心。这是有用的,因为这允许你按照自己想要的、能够理解的格式来写代码。你可以通过空白将一些代码放在一起,或者其它你任何想做的。但是话又说回来,要结束一行代码,你需要一个分号。所以添加下面这两行到你的程序中:
pspDebugScreenInit();
SetupCallbacks();
现在该是写一些我们能够看到实际结果的代码的时候了。还记得我们把"pspDebugScreenPrintf"定义成"printf"吗?好,用它的时候到了。我们通过调用带有一个参数的"printf"函数来向屏幕打印文本信息。参数是你传给一个函数供其使用的一个变量。这些在你以后编写自己的function的时候迟早会有用的。所以,为了使"printf"向屏幕输出,我们需要传给它一个字符串。我们将"Hello World"字符串传给函数就可以将它输出。"Printf"是一个很强大的函数,因为你可以使用它往屏幕上输出其它变量。我们可以把它们作为其它的参数来传递,但是先在还不是要讲这些的时候。就现在来说,我们只是输出"Hello World"到屏幕上,像这样:
printf("Hello World");
到这里,你告诉了"printf"函数向屏幕输出文本。现在我只需要再完成一些东西,我们的源代码就准备好构建了。我们需要暂停程序以便能够看到输出结果。否则,它就会根本没有反应,或者直接返回PSP菜单。你可能永远看不到你那美丽的短语被输出到屏幕上,因为它被非常快地擦掉了。所以添加如下这行代码用来暂停程序,直到"Home"被按下,用户被返回到PSP操作系统。
sceKernelSleepThread();
现在我们需要给函数一个返回值,因为当我们定义它的时候("int main()"),我们告诉编译器它将返回一个整数。所以只要返回一个'0'(这是个零,不是一个大写的'o'),这样做:
return 0;
最后,用一个括号来结束函数:
}
程序这样就写好了!现在我们只要建立一个Makefile来告诉编译器我们想怎样编译这个工程。所以创建一个名叫"Makefile"的文件,主要没有扩展名(比如.txt)。完成之后,用你的文本编辑器打开它。

将以下内容写入Makefile:
TARGET = hello
OBJS = main.o

CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Hello World

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
你可以把这个Makefile用作你所有简单工程的基础部分。有时候你需要添加库文件或其他的到这个文件中,但是现在来说它相当简单。本质上,它只是告诉了编译器去找到"main.c"文件并用PSPSDK来把它构建成一个PSP可执行的.pbp文件。如果你把这个Makefile用于其它工程时,需要改的是"PSP_EBOOT_TITLE = Hello World"这里。你可以把"Hello World"换成你的程序的标题,当你在PSP游戏菜单上选中它的时候这个名字将被显示。

现在打开一个CYGWIN Bash Shell并且"cd"进入你的"projects/helloworld"目录。输入"make"后Shell会为你输出一些东西。它将告诉你你的源代码是否存在使它无法编译的错误(errors)。通常,如果它给你一些警告(warnings),没有什么大问题。错误是你应该注意的,警告只是可能导致bug的地方。注意:如果你的psp的Firmware是1.5版的,你可以通过输入"make kxploit"来代替"make"自动生成两个文件夹。

如果你没有任何错误,祝贺你!你已经成功的创建并编译了你的第一个PSP应用程序。我打赌你现在迫切地想试试它。所以把"C:/cygwin/home/yourUserName/projects/helloworld/EBOOT.PBP"放到你的PSP,就和安装其他自制程序一样,自己试试吧!

要学习更多的PSP编程知识,比如if/then语句,变量,循环,和按钮输入,请看第三课。

注:原文地址http://www.scriptscribbler.com/psp/tutorials/lesson02.htm

由于原文可能不定期更新,所以本译文不保证与原文保持同步

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值