掌叔
2008-06-07 16:10:47
摘自:[url]http://blog.donews.com/pspdoc[/url]
学习了第一课之后,你已经建立了编写psp程序的编译环境。也许你已经迫不及待开始你第一个psp程序。这个教程将为你提供一些c语言的基础知识,并为你的编程之路打下基础。
我们先建立目录来存放我们要编写的程序项目。打开CYGWIN bash shell,键入 "mkdir projects",回车。(mkdir,这个命令是用来建立文件夹或目录的,熟悉linux和unix的朋友一定不会陌生),现在,键入"cd projects"回车,进入projects目录。现在我们再建立另外目录来存放马上要做的"helloworld",所有的编程教程几乎都把"helloworld"当成第一个初学者程序,我们也不例外。
在projects目录下,键入"mkdir helloworld"回车,接着键入"cd helloworld",进入helloworld目录。
打开一个文本编辑器,可以是记事本,wordpad,你喜欢用什么就用什么。我跟喜欢用支持c/c++语法高亮的编辑器,说实话,真实这些都无所谓。现在,在helloworld目录下建立一个名为"main.c"的文件。我们要在这个文件中写下代码段。注意了,激动人心的工作要开始了......
程序的第一部分应该是一些注释段,用来告诉别人我们的程序用来做什么,什么时候写的,谁写的。注释不会被编译器编译、执行,但是它很重要,如果你以后重新编辑你的代码,注释能帮助你快速的重温代码,所有你可以把一些笔记写在注释中。注释以"//"和"/*"符号作为标记。一旦你看见"//",就说明以后的文字都是注释。"/*"和"*/"之间的内容也是注释,被编译器忽略,它们之间的内容可以跨行,但以"//"标记的注释只能是一行。
开始我们的程序吧,先在注释中告诉别人这个程序是什么,谁写的,什么时候写的
// 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"可以引用编译器提供的文件也可以引用你自己建立的头文件。×××××我们的程序中将要引入两个头文件。第一个是"pspkernel.h",每个psp程序都会引入这个文件,它包含了所有为psp准备的代码。如果你不引入这个头文件的话,你的程序将无法在psp上运行。第二个需要引入的文件是"pspdebug.h",这个文件包含了一些调试程序所需要的函数,在屏幕上显示文字的函数在包含其中,它正是我们需要的。那么,在你的程序中,写下:
#include
#include
现在,我们要告诉psp一点点我们这个程序的信息。它不是很重要,程序编译时会忽略它,但是把它写在程序里确实很有用(如果仅仅为了前向兼容)。第一个属性是程序的名字,剩下的属性包括最大版本,最小版本,我们先不去管它们,让它们保持缺省值。好的,接着在你的程序中添加如下
代码:
SP_MODULE_INFO("Hello World", 0, 1, 1);
我们将要建立一个函数用来往屏幕上写字。下面这一步是可选的,但它可以让你的编程工作变的轻松,把psp内置的往屏幕上写字的函数"pspDebugScreenPrintf" 函数改名为"printf",以后我们每次我们使用"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;
}
接下来,我们要定义主函数,每一个c或者c++函数都需要一个主函数也就是 "main"函数,它是一个程序的执行入口。举个例子:
//Do not put this in your program.
//It is an example.
int myFunction() {
//Print Out 'A'
return 0;
}
int main() {
//Print Out 'B'
myFunction();
//Print Out 'C'
return 0;
}
这个程序执行的结果是 B A C,因为程序从main函数开始执行。当它输出B以后,会调myFunction(),这个函数在上面定义过,muFunction()函数输出A之后,程序回到主函数中,继续执行,输出C。所有的c程序都遵照这种线性顺序。main函数对你的程序来说是至关重要的。定义(创建)一个函数,要遵循格式:"[返回值类型] [函数名](参数) {代码段}"。返回值类型是指函数返回给程序的数据的类型。main函数返回值一般是整型(int)。函数名顾名思义,main函数的名字就是main。把以下的代码加入你的程序吧:
int main() {
现在我们需要添加两行代码,做一些关于屏幕的工作并调用前面已经定义的函数(目前为止,我们不知道它如何工作)。尽管你不需要知道那些函数如何工作,但是你必须掌握函数的调用方法。非常简单,函数名+圆括号就行了(如果需要传递参数,把参数写在圆括号里,这个以后我们会介绍的)。程序的每一行都必须以";"结尾,因为编译器看不到空格,即使你在两行中间有100个空行,编译器照样不理会。这样你就可以按你想要的格式编写代码,你可以把代码都写在一行(我不是很赞成),也可以在你想加入空白区域的地方随便添加。但是每行语句的结尾你必须要有分号。
两行代码如下:
pspDebugScreenInit();
SetupCallbacks();
现在是时候写一些代码让我们激动一下了(是不是因为以上的教程太枯燥),为什么激动?因为马上就能看到结果。还记得吗,我们曾经定义"printf"代替"pspDebugScreenPrintf",马上我们就会看到这个决策是多么的英明。我们如何让屏幕上显示文字呢,这需要调用"printf"函数并输入一个参数。参数是一个传递给函数执行的变量。当你编写自己的函数时,它迟早会派上用场。我们需要函数"printf"输出字符"helloworld"到屏幕上,于是我们把"helloworld"当作参数传递给函数。"printf"是一个非常有用的函数,我们也可以利用它输出其他的变量到屏幕上。现在,我们就输出"helloworld":
printf("Hello World");
目前为止,你已经告诉"printf"函数输出"helloworld"到屏幕上,接下来我们需要做一些扫尾工作,然后我们的程序就可以被build了。我们需要把程序暂停一下,不然看不到屏幕上的输出。如果不暂停的话,你看到的结果不是freeze就是回到psp目录,输出的结果一闪而过以致于你根本看不到屏幕上出现那美丽的文字。加入下面一行,可以把输出画面暂停直到你按下"home"键或者回到psp操作系统。
sceKernelSleepThread();
我们还需要我们的函数一个返回值,前面我们已经定义了"int main()",所有返回值必须是一个整型。返回"0"就ok了,它代表正常退出,注意哦,不是"o"
return 0;
最后,加上一个大括号,函数就结束了
}
为了程序的执行,我们还需要编写一个makefile告诉编译器怎么执行我们的项目,创建一个文件"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当作任何一个小项目的模板,有时候你可能需要添加一些库。它告诉编译器用PSPSDK把mian.c编译成psp可以认识的.pbp文件。如果你在以后的项目中需要用到这个Makefile文件,你需要把"PSP_EBOOT_TITLE = Hello World."中的"Hello World"改成你程序的题目,这个题目就是以后将要在psp上显示的游戏目录名。
现在,打开CYGWIN Bash Shell,键入 "cd projects/helloworld",然后"make"回车,你会看到屏幕上显示一些make的细节,如果没有编译成功,它会告诉你是什么错误导致。如果你的程序编译时遇到一些错误,没关系。错误是你需要提防的,可能有些错误为你让人觉得快要疯了。
如果编译过程中,没有任何错误,那要恭喜你了。你已经成功的创建并编译了你的第一个psp应用软件。我敢打赌你急切的想要在psp上实验一下,那么把"C:/cygwin/home/你的名字/projects/helloworld/EBOOT.PBP"拷贝到psp上,自己试一试吧
Lesson 03 将让你学到更多的psp编程知识,比如if/then 语句,变量,循环和按键输入。