在学会架设开发环境,编写第一个程序,领略一些编程技巧,并且涉猎列一些经典程序之后,接下来我们开始第五课,你不要想这里有什么会让你感到惊讶的,这只是通过学习一些高级的概念来增强我们的编程技巧。

高级,这个只是个人看法,我们其实只是增强我们的C基础.以便于将来在真正高级的应用程序上编写程序。学过这节课后,你应该掌握如何"超频"到 psp真正的333MHz的速度。能够将文字讯息显示到屏幕上(图片文本,不是我们之前用的debug文本),并且了解在psp上的颜色工作是如何进行的。

我们所要创建的程序是背景转换,因为我们需要允许用户在背景上选择颜色,所以我们要转换它,并且将转换的颜色元素显示在屏幕上。

首先是关于一些背景知识,这里存在一个关于psp的“超频”的普遍的误解。因为本来观念的原因,人们很容易联想到"超频"会伤害和损坏硬件。说"超频"psp对硬件是危险的,简直是无稽之谈。这种情况并不只是在psp上出现。实际上,psp从出厂后就已经降频。为什么sony这么做,,有几个说法。一种是sony因为它会非常快的消耗掉电池(对我们来说到是无关紧要的,运转UMD比从记忆棒上读取存储需要用掉更大的能量,所以我们在电池寿命的方面已经有一个很大的优势)。另一种说法是sony希望开发者去编写更新的代码。而更多人认同第三种说法(跟我本人的观点也基本相符)是他们希望将来可以通过允许开发者在一些要点上可以用到全速,来推进游戏程序编程的发展。总之,psp正常的运行速度是222MHz,如果你需要更大的力量来运行你的程序,"超频"是一个选择。而我们这里所要编辑的程序,将用不到我上面所说得那些,但是我想这是一个很好地时机来介绍这个概念。

现在,让我们开始我们的程序,你需要下载另外一个压缩文件,你点击”here”可以获得链接。释放这个压缩文件,你需要在文件夹里面创建一个main.c文件。

#include <pspkernel.h>
#include <pspdisplay.h>
#include <pspctrl.h>
#include <stdio.h>
#include <psppower.h>

#include "graphics.h"

假设你已经看过前面几课,这里就没有什么东西是你看不明白的。包括唯一对你有点陌生的"psppower.h"。这个文件包含了我们可以用来快速改变psp时钟的的函数。

列出一些常见的代码:

PSP_MODULE_INFO("Background Changer", 0, 1, 1);

#define RGB(r, g, b) ((r)|((g)<<8)|((b)<<16))

记得在第二课我们只是一笔带过这些代码而没有对他们究竟是做什么用加以解释。现在是时候让你们知道了,第一个参数是你的程序标识符,基本上是你程序的名字。第二个参数允许你传入属性。因为你的大多数程序,你将只是用到一个0,但是如果你编辑一个内核的应用模式,你将需要把它转换成"0x1000",第三个参数是掌管转换(翻译),第四个是辅助转换(翻译)。他们是用来给你的程序的转换数据的。

标准的回叫:
/* 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()主函数。

int main(void) {
scePowerSetClockFrequency(333, 333, 166);

这个数据行是用来设置时钟的频率(丛函数名字就可以很显然地看出来),你可能很奇怪为什么有三个参数,我想问,是否这三个中只有一个是处理器呢?答案是错误的,psp实际上有三个处理器。第一个是CPU(中央处理器),你得几乎所有的程序都需要它来处理。第二个参数是媒体播放器,第三个我该怎么说呢,你可以在你的处理器上运行MIPS 汇编代码。媒体播放器的速度是333 MHz,第三个参数控制图形中心,这就是人们常说得"GPU","GPU"的运行速度在166 MHz,默认的速度是"222, 222, 111."(如果你自己没有改变它的话)。
接下来,我们把它显示在屏幕上,跟我们上一课所作的一样:

SetupCallbacks();
initGraphics();

因为我们的输入需要要被接受,回忆一下第三课所讲的,我们需要定义一个SceCtrlData类型的变量,我们定义它为:"pad."

SceCtrlData pad;

我们再设立两个变量和一个数组:

int i;
int selComponent = 0;
char filler[10];

整数"i,"将被运用到我们接下来的一个循环,字符数组我们把它用作一个字符串来输出一些这个程序之后信息。"selComponent"是我们用作纪录用户是使用哪一种颜色。

下面我们要声明并且初始化的三个变量是用来存储我们的背景信息的。一种颜色是有三种成分构成的:红、绿、蓝。用32位来表示,每一种颜色在的最大值是255。对每一种颜色,零是黑色,255是白色。1~255之间的就是复合色。有时候,你会看到用16位值来描绘颜色。16位是基于16来计算的系统。他是从0运行到F(F就是16)。所以,在32位的系统下,FF=255(即16*16,减1的原因是因为你是从零开始计算的)所以,白色就是"FFFFFF"(255红,255兰,255绿)。总之,我们用这三种变量来存储背景颜色信息:

int bgR = 0;
int bgG = 0;
int bgB = 0;

目前我们的背景是黑色,尽管这样,它也是存储了信息以便于我们可以熟练的运用它。我们实际上并不需要设置背景的颜色为黑色,那需要我们改变这些变量的值。

因为我们需要用"graphics.h"文件而不是用pspDebugScreenPrintf来显示信息,我们需要告诉我们的程序我们要用哪些颜色。

Color highlightColor = RGB(200, 200, 200);
Color dimmedColor = RGB(100, 100, 100);
Color shadowColorH = RGB(55, 55, 55 );
Color shadowColorD = RGB(55, 55, 55 );

首先,我要解释这些数据行在做什么,他们在运用RGB宏,这个我们在第四课已经做以解释—他们把颜色成分转换为单色。"Color" 数据类型在"graphics.c"的包含文件中有定义,你也可以通过u32(一个32位整型)在一些程序中来控制一种颜色。

这节课用到四个变量是因为我们希望加亮这些用户通常转换的颜色成分。所以我们有两个主颜色,一种颜色是为了高亮文字,另一种是为了暗淡的文字。同样,我们有一个动态背景(意味着背景是变幻的)我们将用到一个影子,它可以帮助我们的文档从背景里面突出出来,我试过很多颜色,随意使用这些颜色从而找到你最喜欢的一种。

继续我们的游戏循环:

while(1) {
sceCtrlReadBufferPositive(&pad, 1);

一个标准的无限while循环和手柄控制信息读入的函数

现在我们掌握了手柄控制信息读入的函数,我们所要做的就是用上下键选择颜色。我们用左右键来调节那些颜色。

if(pad.Buttons & PSP_CTRL_UP) {
if(selComponent > 0) {
selComponent--;
}
for(i=0; i<10; i++) {
sceDisplayWaitVblankStart();
}
} else if(pad.Buttons & PSP_CTRL_DOWN) {
if(selComponent < 2) {
selComponent++;
}
for(i=0; i<10; i++) {
sceDisplayWaitVblankStart();
}
}

代码块的应用是前半部分是这样得,如果点击上键,他就会减少变量(因为我们想要从上边开始运行,0是最上边的颜色,1是中间颜色,2是末端颜色)如果按下向下键,他就会增加变量。当某个按钮按下的时候For循环的作用是用来停顿程序一会,这样就大大简化了用户的操作。

下面的代码块是控制左右键的:

if(pad.Buttons & PSP_CTRL_RIGHT) {
switch(selComponent) {
case 0:
bgR++;
break;
case 1:
bgG++;
break;
case 2:
bgB++;
break;
default:
//SHOULD NEVER EXECUTE
break;
}
} else if(pad.Buttons & PSP_CTRL_LEFT) {
switch(selComponent) {
case 0:
bgR--;
break;
case 1:
bgG--;
break;
case 2:
bgB--;
break;
default:
//SHOULD NEVER EXECUTE
break;
}
}

当你看到这些代码,你可能会自问: switch是什么意思?这个问题非常简单,这个比较像if/else。它用到一个变量,"switch(你的变量)”,举例说明,在我们的程序中,"selComponent"变量被限定为:0、1、2,

如果"selComponent"等于0,我们的变量"bgR"将增加1,如果它等于1,"bgG"也增加1,如果它等于2,"bgB"也增加1,这时break语句就会退出转换结构。但是如果他找不到匹配的数值,那么程序将会运行默认的数值。

这样,我们就有了允许我们修改颜色的代码,通过改变变量来改变颜色,下一步所要做的是在屏幕上显示的程序。我们的用户界面(UI)由文本组成,它可以告诉用户,界面的颜色成分和背景。

我们说过,颜色的值是0-255,因为我们需要确认当用户运用它的时候取值不能超过这个范围,所以我们要运用一连串的if/else语句来限定取值范围。

if(bgR < 0) {
bgR = 0;
} else if(bgR > 255) {
bgR = 255;
}
if(bgG < 0) {
bgG = 0;
} else if(bgG > 255) {
bgG = 255;
}
if(bgB < 0) {
bgB = 0;
} else if(bgB > 255) {
bgB = 255;
}

这是一个漂亮的自我说明,如果颜色值超过这个范围,我们把它设置成范围的最大和最小值。

现在根据我们的变量来填充我们的背景颜色。

fillScreenRect(RGB(bgR, bgG, bgB), 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

"fillScreenRect()"是被"graphics.c."定义的一个函数。它是构成了矩形屏幕的特定颜色的一部分,他有五个参数,第一个是矩形的颜色,第二个是矩形的x点,第三个是矩形的y点,第四个是矩形的宽度。第五是矩形的高度。

我们在背景上写文本需要我们键入:

sprintf(filler, " RED: %i", bgR);
if(selComponent == 0) {
printTextScreen(11, 10, filler, shadowColorH);
printTextScreen(10, 10, filler, highlightColor);
} else {
printTextScreen(11, 10, filler, shadowColorD);
printTextScreen(10, 10, filler, dimmedColor);
}

我们在第四课学过"sprintf()"函数,那时我们对"printf()"在字符串中的作用做以解析,这次,我们用到一个变量,我们需要同时显示颜色(红色)和值(bgR)跟第三课的方法相同,我们输入一个整数,(用"%i"),一旦颜色成分被选定,我们就应用来自"graphics.c"的"printTextScreen()"函数来把我们的字符串打印到屏幕上。这个函数分为四个参数,第一个是x点,第二个是y点,第三个是字符串,第四个是颜色。用if/else语句的理由是因为我们想要在不同的被选定的颜色中显示文本。我们也要在文本的下面输入阴影。

同样的方法应用在另外的两种颜色上:

sprintf(filler, "GREEN: %i", bgG);
if(selComponent == 1) {
printTextScreen(11, 20, filler, shadowColorH);
printTextScreen(10, 20, filler, highlightColor);
} else {
printTextScreen(11, 20, filler, shadowColorD);
printTextScreen(10, 20, filler, dimmedColor);
}

sprintf(filler, " BLUE: %i", bgB);
if(selComponent == 2) {
printTextScreen(11, 30, filler, shadowColorH);
printTextScreen(10, 30, filler, highlightColor);
} else {
printTextScreen(11, 30, filler, shadowColorD);
printTextScreen(10, 30, filler, dimmedColor);
}

我们点击屏幕增加一小段的暂停来控制我们程序的速度(我们不希望它运行得太快)最后,修改我们的程序。

flipScreen();

for(i=0; i<1; i++) {
sceDisplayWaitVblankStart();
}
}

return 0;
}

现在,增加一个Makefile,为你的编译做准备。

TARGET = BackgroundChanger
OBJS = main.o graphics.o framebuffer.o

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

LIBDIR =
LIBS = -lpspgu -lpsppower -lpng -lz -lm
LDFLAGS =

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Background Changer

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak

跟第四课的Makefile相同,除了名字和增加的 "-lpsppower," "-lpsppower,"是添加overclocking的库文件。现在你完成了它--背景转换器

PSP dev lesson 05相关推荐

  1. [小北De编程手记] : Lesson 05 玩转 xUnit.Net 之 从Assert谈UT框架实践

    这一篇,本文会介绍一下基本的断言概念,但重点会放在企业级单元测试的相关功能上面.下面来跟大家分享一下xUnit.Net的断言,主要涉及到以下内容: 关于断言的概念 xUnit.Net常用的断言 关于单 ...

  2. [小北De编程手记] : Lesson 02 - Selenium For C# 之 核心对象

    从这一篇开始,开始正式的介绍Selenium 以及相关的组件,本文的将讨论如下问题: Selenium基本的概念以及在企业化测试框架中的位置 Selenium核心对象(浏览器驱动) Web Drive ...

  3. [NEHE Couse] 05.3D Objects

    在这节课中终于从二维平面拓展到三维平面上来了,程序中绘制了两个3D物体,一个是四面体棱锥,一个是一个正方体,为了看起来效果好些,四棱锥每个顶点的颜色都不一样,然后颜色样式采用GL_SMOOTH来控制, ...

  4. 自动调试用于移动GPU的卷积网络

    自动调试用于移动GPU的卷积网络 对特定设备进行自动调试对于获得最佳性能至关重要.这是有关如何调试整个卷积网络的说明文档. TVM中Mobile GPU的算子实现以模板形式编写.模板具有许多可调旋钮( ...

  5. linux video属性_linux查询video设备类型

    想查询 dev/video的类型,找不到命令,闲的蛋疼留个模版 用的时候把video列表写进solve前的 dev_list即可 #include #include #include #include ...

  6. 【Linux】一步一步学Linux——fg命令(130)

    00. 目录 文章目录 00. 目录 01. 命令概述 02. 命令格式 03. 常用选项 04. 参考示例 05. 附录 01. 命令概述 fg命令用于将后台作业(在后台运行的或者在后台挂起的作业) ...

  7. Linux环境无文件渗透执行ELF:memfd_create、ptrace

    <GDB调试之ptrace实现原理> <C语言程序调用栈:backtrace+backtrace_symbols+backtrace_symbols_fd> <strac ...

  8. 数据分析-R语言资料整理

    独家分享--48页PPT解密数据可视化! Excel图表快捷操作小技巧 基于随机森林的分类与回归 R语言制作网页 ggplot2:可视化设计师的神器,了解一下 [译]R包介绍:Online Rando ...

  9. Arch Linux 硬盘引导-联网安装

    Arch Linux 硬盘引导-联网安装 Arch Linux 硬盘引导-联网安装 ============ https://www.archlinux.org/ https://wiki.archl ...

最新文章

  1. Algorithm之PrA:PrA之nLP非线性规划算法+Matlab 优化工具箱的GUI求解非线性规划
  2. C# 3.0实现类本身的方法扩展
  3. Winedit 快捷键概览
  4. vista任务栏透明_在Windows XP中获取Vista任务栏缩略图预览
  5. 深入了解“TXTSETUP.SIF”
  6. C根据输入的城市坐标求各城市间的距离
  7. 超详细,手把手 教你 SQLyog 安装教程
  8. 【最全,带注释版】雷赛运动控制卡库函数C#导出
  9. 什么是广域网(WAN、公网、外网),什么是局域网(LAN、私网、内网)
  10. Python之路【第二十篇】:python项目之旧版抽屉新热榜
  11. win10下卸载office2010(测试多种方法后,成功实现)
  12. flask框架学习笔记
  13. 电脑读卡器,电脑上如何找到读卡器
  14. Network (哈工大网课笔记)
  15. 计算机专业的一些推荐书籍
  16. 小功能⭐️Unity中利用材质自发光实现物体闪烁效果
  17. laradock卡在raw.githubusercontent.com,怎么办
  18. 计算机的打印机的电路图,打印机的工作原理图解
  19. C语言时间库操作-->协调时转本地时
  20. 岁寒,然后知松柏之后凋也。关于后凋的解释

热门文章

  1. 2021年中国农贸市场发展现状:农贸市场仍是消费者购买生鲜农产品的主渠道[图]
  2. MySQL作业(一)——单表查询
  3. java docx转pdf_如何在Java中将DOCX转换为PDF
  4. Echarts自定义工具栏toolbox
  5. C# 使用tableLayoutPanel控件实现窗体布局
  6. python设计个人简历、博客_Python基础
  7. 蒸汽机器人布里茨天赋_lol机器人S6天赋加点图|2016赛季英雄联盟蒸汽机器人布里茨S6天赋、出装、符文加点最新全攻略_好特教程...
  8. 支付宝批量转账到零钱
  9. 尾款人的双11焦虑症:配送机器人能解?
  10. java常用的jar包_Java中常用的jar包有哪些