PSP Coding


 
HomeCalendarFAQSearchMemberlistUsergroupsRegisterLog in

Share | 
 

 Starter C/C++ Tutorials

Go down 
AuthorMessage
-LeetGamer-
Admin


Posts : 247
Points : 397
Reputation : 4
Join date : 2010-09-29
Age : 25

PostSubject: Starter C/C++ Tutorials   Thu Sep 30, 2010 9:29 am

All tutorials by www.PSP-Programming.com

-Will update this post later-

Just google how to install PSPSDK (It's so much better than Cygwin)


Last edited by -LeetGamer- on Mon Oct 04, 2010 1:00 pm; edited 5 times in total
Back to top Go down
View user profile
-LeetGamer-
Admin


Posts : 247
Points : 397
Reputation : 4
Join date : 2010-09-29
Age : 25

PostSubject: Re: Starter C/C++ Tutorials   Thu Sep 30, 2010 9:29 am

Lesson Two

Part One

Quote :

So, after reading Lesson 01, you have a working development environment in which to create your programs. Now what? Well, this is the part you've all been waiting for, your very first program for the PSP. This tutorial will explain the basics of the C programming language and build the foundation upon which you will build your kingd-- err... programs.

If, at any time in this tutorial, you need help please head over to our forums and post a question. We are always happy to help a fellow programmer.

We're going to create a folder hierarchy to organize our projects. Open up a CYGWIN bash shell, and type "mkdir projects" and then hit enter. This command ("mkdir") stands for "make directory" and it will create a directory, or folder, in your current operating directory. So now we have a new folder for all of our projects, navigate into it by typing "cd projects" and hitting enter. Now we are going to create another directory for this specific project. Type "mkdir helloworld" and hit enter. Now switch into the new directory with "cd helloworld."

The next step is to open up a text editor. It doesn't really matter what you open, it can be Notepad, Wordpad, whatever you want. I prefer using an editor that is dedicated to editting C/C++ source code because of the syntax highlighting options that are built in (I use Dev-C++), but honestly, it doesn't matter (so long as you know how to use it).

Now, create a new file and call it "main.c" in our "helloworld" directory. This is going to contain the source code for our program. For those of you who don't know what source code is (and I know there will be a few), the source code is what we write to create a program. It is written in a way that humans can understand. In most languages, the source needs to be converted to a format the computer (or in our case, the PSP) can understand. These are called compiled languages, and C and C++ fall into this category (the conversion is done by the compiler that we set up in Lesson 01). There are a few other programming languages that use what is called an interpreter to interpret the source code and send out machine code on the fly. These are called scripting languages (an example of a scripting language is PHP).

Alright, so we have a new file that is going to hold our source code. Now we need to start writing it. The first part of the program should contain comments to tell anyone reading our code what the aim of the program is, when it was written, and who the author is. Comments are lines of source code that are omitted from the compiled binary (or skipped by the interpretter in scripting languages). Comments are a very important part of your code, because when you (or someone else) come back to edit your source code later, you will not remember all of the intricacies of the program. So, you can leave yourself notes in the form of comments. Comments are signalled with the "//" and "/*" characters. Any time you see a "//" it means that the rest of the line will be a comment. A "/*" means that the compiler (or interpretter) will ignore your code until it reaches a "*/" signal. Comments signalled by the "/*" operator can span many lines, but comments signalled with "//" only comment out the rest of that line.

So, to start off our program, we are going to leave a comment at the top about what it does, when it was created, and who it was written by.
// 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.
*/
The next portion of the program is where we tell the compiler which header files and which include files we are going to use in our program. Basically what the "#include" directive does is copy the code from the file you pass to it into the top of your program. This allows you to keep your program simple, while still using the advanced code that is already written for you. The include directive can include either header files that came with the compiler (or that you add to the compiler), or header files specific to the specific project that you are working on. The way that you discern which of these you are including is by whether you use "<>" to enclose the file or if you use quotes to do it. The less than and greater than signs include a file from the compiler's "include" directory, and the quotes include a file from the same directory as the file including them. We will be including two files in our program. The first is "pspkernel.h." This file will be included in every single program that you write for the PSP. It contains all of the code specific to your PSP. Your program will not work on the PSP if you do not include this file. The second file we are going to include is "pspdebug.h." This file contains several useful functions for debugging your programs, but specifically it includes the function that we are going to use to write text to the screen. So, add this code to your program:
#include <pspkernel.h>
#include <pspdebug.h>
Next we tell the PSP a little bit about the program. This isn't really that important, your program will compile without it, but it is always a good idea to keep it in (if only for forwards compatibility). The first attribute is the name of the program, but it's not really the name of the program that will appear (we'll change that later). The other values are other attributes (just leave it alone), major version, and minor version. We'll just leave all of these except for the name as the defaults. So, add the following line to your program:
PSP_MODULE_INFO("Hello World", 0, 1, 1);
Now we are going to set up the function that we will use to write to the screen. This step is optional, but it makes writing text based programs much easier. The basis behind this line is to change the function that is built into the PSP, called "pspDebugScreenPrintf" into something that's much easier to type. This function is used to write to the screen (which you will see later). What we are basically going to do here is rename "pspDebugScreenPrintf" to "printf." So every time we use "printf" from now on, the compiler will just treat it as if we have typed "pspDebugScreenPrintf." Here's how we'll do it; we'll define "printf" as "pspDebugScreenPrintf" like this:
#define printf pspDebugScreenPrintf
Take a deep breath. Ok, now breath out. Good. Now continue to the second part of the tutorial.

Part Two

Quote :

Alright, here we are in the second part of Lesson 02. If you somehow got here without reading the first half you will definitely want to go back now or you will be very confused.

Ok, I have some bad news and some good news. The bad news, the next block of code is pretty complicated. The good news, you don't need to understand it. Here's a brief explanation of what it does (we'll leave the actual syntax and line-by-line explanation until later). Basically what this block of code contains is functions that will be called in our program. The functions will set up your program to run on the PSP and allow you to not worry about your PSP freezing or exiting the game when you don't want it to. Put this block into your program:

/* 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;
}
Next, we are going to define the "main" function. Each program in C and C++ needs a main function. This is where the code is executed from. C (and some of C++) functions in the proceedural paradigm. This means that the code goes in a linear path. For example, if you have the following code:
//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;
}
Where the comments (see above if you don't remember what comments are) do what they say. The program would print out 'B' then it would print out 'A' then 'C' because the compiler starts in the main function. It prints out 'B' then it sees the call to "myFunction" which is defined above it, and goes there, sees that it needs to print out 'A' and then returns to where it left off and prints out 'C.' All of your programs (until you get to advanced C++) will follow this linear structure. So, the "main" function is vital to your program. To define a function, you use the following structure: "[return type] [function name]() {". The return type is what the function will send back to the program. For "main" this should always be of type "int" (which stands for integer). The function name is your name for the function, "main" will obviously be named "main." So, define your function by putting the following line in your code:
int main() {
Time for another deep breath. You're doing well. The third (and final) part of the tutorial is where we will put in the meat of our program. So when you're ready, proceed.

Part Three

Quote :

Here comes the third part of Lesson 02. Parts one and two are prerequisites, so go back and hit those first before you come back and complete this part. Here it goes.

We now need to add two lines to set up the screen and to use those functions that we put in earlier (which you didn't need to know how they worked). Even though you don't need to know how those functions worked, it is important to grasp the concept of how to call functions. It is actually very simply. You just put the function name with parenthesis at the end (and if it takes any parameters, you put those in the parenthesis, but we'll cover that later).

Every line in your program will need a semicolon at the end. The reason for this is because the compiler does not see any white space. Between lines, you could have 100 empty lines, and the compiler wouldn't care. This is useful because it allows you to format your code how you want, in a way that you can understand. You can group lines together, or do whatever you want with your white space. But, in turn, to end a line, you need a semicolon. So add these two lines to your program to set it up:

pspDebugScreenInit();
SetupCallbacks();
Now it's time to write some code that we will actually be able to see the results of. Remember when we defined "pspDebugScreenPrintf" as "printf?" Well, now it's time to use that function. The way that we will print text to the screen is by calling the "printf" function with a parameter (I told you we'd cover it later.) A parameter is a variable that you can pass to a function for it to use. These will come in handy later when you're writing your own functions. So, for "printf" to output to the screen, we need to pass a string to it. We will output "Hello World" by passing that string to the function. "Printf" is a powerful function because you can also use it to output other variables to the screen. We would pass these as other parameters, but that will all come in due time. For now, we will just print out "Hello World" to the screen, like so:
printf("Hello World");
And there it is, you have told "printf" to output to the screen. Now we just need to finish some things up and then our source code will be ready to build. We need to pause our program so that we can see the output. If we don't, it will just either freeze, or return you to the PSP Menu. You will never even get to see your beautiful phrase outputted to the screen because it will be erased so fast. So, add this line to pause the program until the "Home" button is pushed and the user is sent back to the PSP Operating System.
sceKernelSleepThread();
Now we need to give our function a return value, since when we defined it ("int main()"), we told the compiler that it would return an integer. So just return a '0' (that's a zero, not a capital 'o') by doing this:
return 0;
And finally, end the function by putting in a closing bracket:
}
And that's it for the program! Now we just have to tell the compiler how we want this project compiled by creating a Makefile. So create a new file called "Makefile" with no extention (ie, no .txt). Once you've done this, open it up in your text editor.

Put the following in your 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
You can use this Makefile as a basis for all of your simple projects. Sometimes you will need to add libraries or whatnot to this file, but for now it is fairly simple. It basically just tells your compiler to take "main.c" and build it using the PSPSDK into a .pbp file that your PSP can read. What you will need to change if you use this Makefile in other projects is where it says "PSP_EBOOT_TITLE = Hello World." You can change where it says "Hello World" to the title of your program, this is the name that will appear on the PSP Game Menu when you select the file.

Now open up a CYGWIN Bash Shell and "cd" into your "projects/helloworld" directory. Type "make" and your shell should output some stuff to you. It will tell you if your source code had any errors that made it uncompilable. Generally, if it gives you a few warnings, it's not a big deal. Errors are what you want to watch out for, warnings are just possible points that could cause bugs. Note: if you have Firmware Version 1.50, you can automatically generate your two folders by typing "make kxploit" instead of "make."

If you didn't have any errors, congratulations! You have successfully created and compiled your first application for the PSP. I'll bet you're dying to test it out. So, put "C:/cygwin/home/yourUserName/projects/helloworld/EBOOT.PBP" on your PSP just like you would any other homebrew application, and try it out for yourself!

Check out Lesson 03 to learn more about programming for the PSP, such as if/then statements, variables, loops, and button input.

Be sure to add the feed to your RSS Aggregator (or Google Homepage, or Firefox Live Bookmark) to stay updated with the latest tutorials.

If you have enjoyed this tutorial and have a spare buck or two, please consider donating to the author. Or, if you have a website, link to this tutorial series (helping spread the word means more homebrew for all!).

If there's a calling, I will consider making more tutorials. Please contact me with your feedback on the tutorials and on what you'd like to see in the next lessons. My AIM is Yeldarb2k3, and my e-mail is Yeldarb [at] Barbdwyer [dot] com. Also, if you are looking for someone to design you a website, please contact me through my site, Barbdwyer Web Design.
Back to top Go down
View user profile
-LeetGamer-
Admin


Posts : 247
Points : 397
Reputation : 4
Join date : 2010-09-29
Age : 25

PostSubject: Re: Starter C/C++ Tutorials   Thu Sep 30, 2010 9:30 am

Lesson Three

Part One

Quote :

After reading Lesson 01 and Lesson 02, you should now have a development environment set up, and have compiled your first basic program for the PSP. Now it's time to move on to bigger and better things. A "hello world" application is fine and dandy, a great learning experience, but it doesn't do anything. That's what this tutorial is about. How to make your programs do things.

What you need to understand is that this tutorial is not meant to be the be all and end all of PSP programming. It is much less a "how to create a game" than it is a foot in the door. What you will gain here are the basic building blocks of PSP (and C) programming. You will need to rearrange and add to these blocks together to create your own, functional application.

Having read Lesson 02, or knowing how to set up a basic program is a prerequisite for this tutorial. We will not go through the process of setting up your program in this tutorial. So, to test the code that follows replace the line
printf("Hello World.");
from Lesson 02 except where otherwise noted. Since the other lines were just setup for our program, we need not go through what they do again.

The final product of this tutorial will be a program that counts upwards until the user presses a button or until the counter hits a predefined limit. This is the perfect application for this tutorial; it combines several core elements of C programming to create a simple, yet useful result without requiring many program-specific functions. Covered in this tutorial are: variables, if/then statements, loops, text formatting, and button input.

First off, we will need to add two more header includes. The first one is to give us a little more control over the screen (we need this for one of the functions we will be using later). The second file we will be including allows us to get button input. So to do add these two files (pspdisplay.h and pspctrl.h), we need to add these two lines right below our first two "#include" statements:
#include <pspdisplay.h>
#include <pspctrl.h>
And that's all the extra setup we need. Now we'll move on to putting in the functional code. From here on, all code listed should go in your main function, replacing the "printf" statement from Lesson 02. The first thing we will do is declare the variables that we will use in our program. A variable declaration takes the following form:
//EXAMPLE (Psuedo Code)
//DO NOT ADD TO YOUR PROGRAM
type name=value;
The type is the data type of variable. Each data type can contain data (and only that data). For example, type "int" (meaning integer) can hold any non-decimal number from -32767 to 32767. A "float" is like an "int," but it can hold decimals. The "char" type can hold a letter. For our program, we will only use the built in type "int" and a PSP specific type called "SceCtrlData" which holds the button state of the PSP controls.

So, to declare the two variables that we are going to use, we insert the following two lines of code into our program (these should go where your "printf("Hello World.");" line was in Lesson 02; right after the line "SetupCallbacks();."
int counter = 0;
int i = 0;
SceCtrlData pad;
So now we have three variables that we can use. Two of type "int," named "counter" and "i," containing a value of zero for now. And one of type "SceCtrlData," named "pad," which is filled with junk at the moment (since we haven't yet initialized it). This is something to keep in mind when writing your own programs. If you declare a variable without initializing it (like our pad variable), it will not just be empty. It will contain the information that was previously in that chunk of memory. Declaring the variable just allocates a certain amount of memory space for the variable to be stored in. The initialization is what clears it out and allows us to use it. The reason that we haven't initialized "pad" at the same time that we declared it is because it wouldn't really make sense. Since it holds button input, you can't just initialize it by typing in a value. We'll initialize it later, before we use it for anything.

Now we're going to give the user some instructions. The way we do this is by using "printf" to output a statement to them. So put this after the variable declarations:
printf("Press [X] To Start the Timer");
Look familiar? Good. It's the same function we used to output "Hello World" in Lesson 02. So if you ran the program at this point, it would be just like the "hello world" application, except it would print out "Press [X] To Start the Timer" instead of "Hello World."

Now we need the program to wait until the user presses the [X] button before it does anything else. Now, this could be a very difficult, nearly impossible thing to do. Fortunately, we have something perfect for dealing with it. It's called a loop. Basically what it does is run through a block of code multiple times. There are different types of loops available to you (for loops, while loops, do while loops, etc), but this tutorial will only introduce two of those loops, the "while" loop and the "for" loop. How this loop works is that you give it a statement, and it will execute a block of code while that statement is true. For example, if you had a block of code that incremented a variable (starting with a value of zero) by one each time the loop was run, and the statement that you passed in the loop was "i<10" it would execute your code ten times, because on the eleventh time that it checked the value of the variable, it would be 10, which is not less than 10, so the statement would be false (man, this is a run on sentence if I've ever seen one). One other important concept that you will need to grasp is that "true" and "false" are synonymous with "1" and "0" respectively.

Phew. It's not so hard is it? I'm glad you agree (like how I just assume the answer to my rhetorical questions because you can't answer?). So let's move on to the second part of this tutorial.

Part Two

Quote :

This is part two of Lesson 03. If you haven't read part one, go back and do that now or you will be hopelessly confused. Continuting on:

Our loop will not be of the classic form. It could easily be, but I've looked through a handful of PSP projects' code, and they always do it this way, so I figured it would be good to introduce you to the way that you will most commonly see. Anyway, what we will be doing is having an "infinite loop" per say. It's not really infinite though, because (as I so conveniently didn't mention earlier), there is another way to exit a loop other than the control statement returning false. That is the "break" statement. Any time this is encountered, it will exit out of the loop you are currently in and your program will continue executing at the end of that loop. So, here's the start of our loop:

while(1) {
As you can see, this control statement will always evaluate to "true," because "1" is the same as "true." So the following code (the lines between the opening bracket and the ending bracket) will execute repeatedly until it encounters a "break" statement.

The next line is where we set the value of "pad." It uses a function that is defined in the "pspctrl.h" file that we included earlier. This is a function call, as you saw in Lesson 02, but there's a little bit of a twist. First of all, we are passing two values to it. No big deal here, you just seperate the two values with a comma. The second thing that's a little different is that we are going to pass a variable. Not a big deal here either, just insert the variable name instead of a number or string or whatever. The third thing that's quirky is that we need to pass it with the "&" operator in front of it. This is actually the "address of" operator, and when you get deeper into programming, you will probably get familiar with it. Basically what it does is instead of passing the value of the variable, it passes the memory address. For now, just know that in order for a function to be able to change the value of a variable you pass to it, you need to use the "&" operator. So here's how we'll set "pad" to contain the current status of the PSP controls:
sceCtrlReadBufferPositive(&pad, 1);
If you're wondering what the "1" is for, don't worry about it. It sets the number of buffers to read, but I've only ever seen "1" used there. Honestly, I don't know why you'd want anything else there (if there's a reason, someone please enlighten me, and I can add it here).

The next line is an "if" statement. It's how you can program logic into your applications. What it does is execute a block of code "if" a statement evaluates to true. So, what we want to do is "break" out of the loop if the [X] button has been pressed. Which, effectively will "unpause" our program and go on to the next section. If the statement evaluates to false, it will just skip the code, and if there's an "else" statement, execute that block of code, or just go on. We will not have an "else" statement, so it will go through the loop again, continually checking the status of the buttons, and seeing if the [X] button has been pressed. While we're at it, we'll close our loop by ending an ending bracket.
if(pad.Buttons & PSP_CTRL_CROSS) {
break;
}
}
The statement in the "if()" translates to English as "if the [X] button is pressed." So if that button is pressed, it will break, if not, it will just continue going through the loop. Now on to the counter.

After they press the [X] button, we want to start a counter that will go until the user presses the [O] button. So what do we do? You guessed it, another loop! So we'll start this loop, and add in the exit code (with the substitution of "PSP_CTRL_CIRCLE" for "PSP_CTRL_CROSS").
while(1) {
sceCtrlReadBufferPositive(&pad, 1);
if(pad.Buttons & PSP_CTRL_CIRCLE) {
break;
}

Now, we need to use a new function. What it does is clear the screen. Since we still have the "Press [X] To Start the Timer" on the screen, we need to erase that. Plus, the next time the loop rolls around and this code is executed, there will be the text that we're going to print out on the screen. We need to clear this off. So here's how we do it:
pspDebugScreenClear();
This will clear off the screen, so now we're ready to print out our counter (and tell the user how they can stop the counter and exit the program).

The first line should look familiar. It's just a simple "printf" statement. The one thing that may look a little weird to you is the "\n" at the end of the string. "\n" is a special character that stands for a new line. So the new line character is the equivelant of pressing "ENTER" on your keyboard. The second "printf" statement is just a bit different. We need it to print out our "counter" variable. To do this, we will use the "%" operator. Basically this signifies that you want to display a variable, and the character that follows it tells the program what type of variable. For an integer, we will use "i" (integer; get it?). The second parameter that we will pass is which variable we want it to print. In our case, we want to pring the "counter" variable. So put these two lines in your program:
printf("Press [O] To Stop the Timer\n");
printf("Counter: %i", counter);

We've completed the second part of Lesson 03. Let's move on to the third part in which we complete our program. Continue.

Part Three

Quote :

Now for the third and final section of Lesson 03. If you haven't read the first or second parts, rewind and come back later.

The next thing we need to do is increase our counter by one so that the next time through the loop, the number displayed is one higher. It wouldn't really be a counter if we didn't do this, now would it? We could do this in one of two ways. The first, less commmon way to do this would be by setting "counter = counter+1;" this works perfectly well, but there is an easier way. To increment a variable by one, just use the "++" operator:

counter++;
It does the same thing as "counter = counter +1;" but it's a bit more elegant, don't you think?

Now we need to insert a short pause to make the "HOME" button work. Here we will be utilizing a "for" loop. This loop is just a tad bit different than the "while" loop. It takes three parameters. The first is the initialization; it will set the variable for the start of the loop. The second is the control statement, which does the same thing as the control statement in the "while" loop. And the third is what you want to happen to your variable at the end of each loop.
for(i=0; i<5; i++) {
sceDisplayWaitVblankStart();
}

This will execute our line of code 5 times (when i = 0, 1, 2, 3, and 4).

And finally, we need to end the code block that the loop runs through with a simple ending bracket:
}

Now for the final little bit. This is the code that will run after the "break" statement executes. We want to display a simple message, and the final count of our counter. So we'll clear the screen and use two more "printf" statements like we did in the loop, but with different text. Add:
pspDebugScreenClear();
printf("Counter Finished.");
printf("Final Count: %i", counter);
And we're done with our code! Now for a couple of cosmetic changes from Lesson 02.

The Makefile needs to be changed to reflect our new program. Go into it and change the title to one that you think suits the new program. I named mine "Counter Program." And also change your target to "count." Now go ahead and build your program, and give it a test run. You should now have the basic skills you need to create your own programs (text based ones at least). You can check out some other C programming tutorials for information on how you can use more complex logic structures (if/if else/else), loops, functions, pointers, etc. There are a few differences with programming for the PSP, but the basic stuff is all straight-up C. Good luck, and have fun!

Update: Lesson 04 - Simple Image Processing is now up!

Be sure to add the feed to your RSS Aggregator (or Google Homepage, or Firefox Live Bookmark) to stay updated with the latest tutorials.

If you have enjoyed this tutorial and have a spare buck or two, please consider donating to the author. Or, if you have a website, link to this tutorial series (helping spread the word means more homebrew for all!).

If there's a calling, I will consider making more tutorials. Please contact me with your feedback on the tutorials and on what you'd like to see in the next lessons. My AIM is Yeldarb2k3, and my e-mail is Yeldarb [at] Barbdwyer [dot] com. Also, if you are looking for someone to design you a website, please contact me through my site, Barbdwyer Web Design.
Back to top Go down
View user profile
-LeetGamer-
Admin


Posts : 247
Points : 397
Reputation : 4
Join date : 2010-09-29
Age : 25

PostSubject: Re: Starter C/C++ Tutorials   Thu Sep 30, 2010 9:31 am

Lesson Four

Part One

Quote :

Since Lesson 03 was released, I have been bombarded with e-mails, instant messages, phone calls, and even the occasional reader banging on my front door pleading with me to release another tutorial. Overwhelmingly they have requested a lesson on adding images to their programs. Well, you guys can finally stop all of that, because this long overdue article is finally here.

At this point, I'll assume that you already have CYGWIN and the PSP toolchain installed, understand how to compile source code into an EBOOT suitable for execution on the PSP, and have at least a basic understanding of the C programming language. If you don't meet these prerequisites, have no fear, read Lesson 01, Lesson 02, and Lesson 03, and then come back.

If it has been a while since you have updated your toolchain, you will need to do that since png.h is necessary for this tutorial and was not originally included in the PSP toolchain. Revisit Lesson 01 if you need a refresher on how to do that. I had to update before I was able to compile this program (if you already have CYGWIN installed, you can skip right to the step where you download the toolchain).

I would like to thank Psilocybeing for allowing me to use his example source code as a base for this tutorial. I had originally planned on using my own example code (adapted from Shine's original Snake game in C) to demonstrate, but that code is antiquated and unnecessarily complex. One major benefit of Psilocybeing's code is that all of the functions and datatypes are defined in external files, allowing you to more easily integrate the code into your own projects.

Before we do anything, we will need to install some new libraries from SVN. What's SVN you ask? Well, SVN is a version management system (it is shorthand for "subversion"). What we will be doing is grabbing some code from online to add more functionality to our compiler. The packages that we will need are zlib and libpng. zlib is a compression library and libpng allows us to work with PNG files (a type of image). To install these libraries, we will need to type the following things into a CYGWIN Bash Shell.
svn checkout svn://svn.pspdev.org/psp/trunk/zlib
"Checkout" is basically SVN's way of saying "download." This will download the zlib source into a folder called "zlib." It will take a minute, a bunch of stuff should scroll down the screen and you should be left back at the "$" for input.

So now we need to compile this new library, so we'll "cd" into the new folder.
cd zlib
We are now in the zlib folder, and are ready to compile. So, like any other thing that we want to compile, we just need to type
make
And voila, it compiles the library for us.

Now we need to put the resulting files into a place where the compiler can access them. So, we'll install them:
make install
And BAM! We've installed zlib. Now wasn't that simple?

Now for libpng. We just need to do the same thing, except we'll substitute "libpng" for "zlib."
cd ..
svn checkout svn://svn.pspdev.org/psp/trunk/libpng
cd libpng
make
make install
And there we are, ready to use PNG's in our program.

Now we'll just clean up those install files by deleting them. To delete things via a Linux shell (which is what CYGWIN emulates), you use the "rm" command. We don't only want to delete one file, though, we want to delete a whole folder and all of its contents, so we'll add the "-R" modifier to it to signify a recursive removal. Basically this just means we want to delete a folder and everything inside of that folder. We'll also use the "-f" modifier to force the deletion of write-protected files so that we don't have to hit "y" for each file we want to delete. So we'll "cd" back to the parent directory and remove both the "zlib" and "libpng" temporary folders that we just created.
rm -Rf zlib
rm -Rf libpng
Now that we have that out of the way, we are ready to start programming.

We'll move on to the second section of this tutorial to continue our program.

Part Two

Quote :

Now that we have everything set up (you should after the first part of Lesson04) we can start. This is the second page of Lesson 04. If you haven't read the first page, you need to go back.

So, to start our program, download this file and extract it into a new folder in your ~/ directory. What's that you say? You don't know what the ~/ directory is? That's alright; unless you have experience with *nix, you wouldn't have any reason to. Basically, ~/ is synonymous with a user's home directory on a *nix system. So ~/ is equivalent to C:/cygwin/home/yourUserName. So, create a directory there and extract the files you just downloaded into that folder.

Now open up your editor and create a new C source file. Name it "main.c" and save it in the folder you just created. From now on I will refer to this folder as your project folder, just for redundancy's sake. Insert the standard comment into the top of your new file, stating the purpose of the program, your name, and the date. This step is (again) optional, but it is a good programming practice to include it.

/*
My Image Display Program
Author: Brad Dwyer
Date: 12/28/2005

Thanks to Psilocybeing for the base code.
*/

Simple enough so far, right? Next we'll add our include files. If you recall from Lesson 02, included files allow us to use prewritten and external functions and datatypes without having to include the behind the scenes code that makes them work. Programming with images ups the ante a bit, and we will have to include quite a few files:
#include <pspdisplay.h>
#include <pspctrl.h>
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspgu.h>
#include <png.h>
#include <stdio.h>
#include "graphics.h"
So we have the standard pspdisplay.h, pspkernel.h, and pspdebug.h. And then we have the pspctrl.h file which allows us to read input from the PSP's keys (as you should remember from Lesson 03). And then we have three files that probably look foreign to you. The first, pspgu.h gives us access to hardware acceleration, we won't be using any of the functions from this file, but it is used behind the scenes by graphics.h (which we will discuss shortly). The second, png.h, allows us to manipulate PNG image files. And the third, stdio.h gives us access to some standard C functions that we will take advantage of. Specifically, we will be using sprintf() to parse strings. And then finally we have an include that looks a bit different. Rather than using the less-than and greater-than characters, it uses quotes. These quotes signify that it is included not from the compiler's include directory, but from the project folder. This file, graphics.h, is the one that we downloaded, and it contains several functions that will make our job a lot easier, including the actual functions that we will use to load and display our image.

Now we'll put in the #define statements, you should already be familiar with the first, but the second will probably throw you for a loop:
#define printf pspDebugScreenPrintf
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
This second #define is actually defining a function; but it is doing it in a shorthand form. This type of definition is called a Macro Function. It accepts the parameters X and Y, and then will run them through the function, which basically amounts to an if statement. Basically, what this function will do is return the value of X if it is greater than Y, or the value of Y if X is less than Y. The syntax of a Macro Function is "NAME (TEST ? TRUE : FALSE)" where NAME is the identifier, TEST is the equivalent of what would go in the parenthesis of an if statement, TRUE is what to return if the TEST result is true, and FALSE is what to return if the TEST result is false. It is the equivalent of the following function:
//THIS IS AN EXAMPLE; DO NOT ADD IT TO YOUR CODE
int MAX(int X, int Y) {
if(X > Y) {
return X;
} else {
return Y;
}
}
You will likely encounter the abbreviated syntax if you delve into other people's source codes, so it is important to understand how it works. Or at the very least understand what it does. The advantage of using this syntax over an if/else structure is that the compiler can often optimize this code better, resulting in slightly faster execution. It's probably insignificant except for those programs that push the hardware to its limits and need that little extra "umph."

That concludes part two of Lesson 04. Continue on to part three.

Part Three

Quote :

And we're back. This is the third part of Lesson 04. You shouldn't be here if you haven't completed parts one and two, so you should probably do that now.

After that bit of a headache at the end of the last section, the next line should be a nice refresher. It's just the simple module definition that we have used in all of our other programs:
PSP_MODULE_INFO("Image Display Program", 0, 1, 1);
Again we will add some familiar code, our standard callbacks.

/* 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;
}
Look familiar? Good.

Now we get to the good stuff; it's the start of our main() function.
int main() {
char buffer[200];
Image* ourImage;
Up to this point, all we have done with strings is display them on the screen through the use of printf(). That's fine and dandy, but it's about time we get a little more in depth about what a string actually is. Basically, in C a string is an array of characters. There isn't such a thing in C as "myString," it is really just 8 character variables placed next to each other in memory. So to allow us to create a string, we have to first allocate that memory, because as soon as we do anything else (define a variable or whatnot), the memory space next to that allocated space next to the string will be reserved and therefore our string won't be allow to extend into it. Well, it will, it's called a buffer overflow, but we're not concerned about that right now; just know that it's generally a bad thing and will freeze your PSP. So to define an array in C, you simply add on how large you want the array (of a given type) to be in brackets after the variable name. So, when we use the line char buffer[200], we are allocating a block in memory of 200 character variables. This is the maximum length that our string can be, 200 characters. There is a way to change the size, but that's beyond the scope of this tutorial.

The second line in our main() function defines a new variable named "ourImage" of datatype Image; it is actually more of a linked list, but don't worry about that for now. This Image datatype was defined in the graphics.h header file which we included. Everything that we do with it will be through the use of other functions in that graphics.h file. Aren't you glad we are using that file? Otherwise this program would have been a major headache.

Guess what? That completes the third part of the fourth lesson. We're chugging quite along so let's continue to part four.

Part Four

Quote :

We're getting close to having a functioning program. This is part four of Lesson 04. If you haven't read parts one, two, and three, go start this tutorial from the beginning.

Now we have a few lines of setup code.
pspDebugScreenInit();
SetupCallbacks();
initGraphics();
The first two lines of this code are the same as what we have been using in other programs to set up the screen. The third line calls another function in graphics.h that gets the PSP ready to display graphics; it does all of the initial setup.

That's all of the setup that we needed to do before actually working with our images. Now we'll move on to loading our PNG file.
sprintf(buffer, "ourImage.png");
ourImage = loadImage(buffer);
The first line of this code is similar to a printf() call. But instead of printing to the screen, this line prints into a string. It's very useful, trust me, before I knew about this function, I tried to write my own. Man was that a mistake. The first paramater that sprintf() takes is the character array (AKA string) that you want to output to. We're using the buffer array that we defined above. And then the rest is like a printf(). We only wanted to store the path of our image into the buffer, but if we had wanted to, we could have used this to insert variables into a string as well, by parsing them the same way as with printf() (if you don't remember how to do this, maybe a revisit to Lesson 03 is in order.

The next line loads our image into the ourImage variable that we defined earlier. loadImage() is another function that is defined in that graphics.h file. It takes one parameter, and that is the string containing the path to the image.

Now we'll do a quick check to see whether our loading of the image was successful:
if (!ourImage) {
//Image load failed
printf("Image load failed!\n");
} else {
If the loadImage function encounters a problem, it will set the value of our variable to 0 (or false), alerting us of the error. So we check this with a simple if statement, and if there was a problem, we print out a short error message.

Hopefully we won't encounter a problem loading the image, and if not, then the following code will execute:
int x = 0;
int y = 0;
sceDisplayWaitVblankStart();
This is just setup for our image display, it shouldn't look too foreign to you, it just declares and initializes a couple of integers and then calls a sceDisplayWaitVblankStart (if you'll remember, this is the same function we used when we were reading from the control pad). This allows the "Home" button to work.

Now we will loop through the entire screen. The screen is 480 pixels wide and 272 pixels high:
while (x < 480) {
while (y < 272) {
These are simple while loops, you should remember them from Lesson 03. The outer loop will continue while x is less than 480 (the screen's width), and the inner loop will continue while y is less than 272, the screen's height.

Now inside there, we are going to put the code to blit (or display) our image.
blitAlphaImageToScreen(0 ,0 ,32 , 32, ourImage, x, y);
y += 32;
}
This first line is your key. It will display a 32 bit image on the screen. That includes an alpha channel! Alpha is another word for transparency. The blitAlphaImageToScreen function takes seven parameters. The first two are offsets. If you are using seperate PNGs for each of your images, these should be zero. What these two parameters allow for, though, is for you to have one master image file containing all of your sprites. Basically, if you have two images in the same image file (next to each other for example), you can use the offsets to tell your program which part of the master image you want to display. The second two parameters are for width and height respectively. Since our image is 32 pixels by 32 pixels, we are using 32 for both of these values. The fifth parameter is to tell the function which image variable you want to use (obviously we're using our ourImage variable). And finally, the last two parameters are for setting the x and y positions of the image on the screen. In programming, this is like an inverted coordinate plane. The x axis is the same as it would be in math (that is, it increases as you move from left to right). The y axis, on the other hand, is upside down; as you increase the y, you move DOWN on the coordinate plane. This can be confusing at first, if you're used to math coordinates, but you'll get the hang of it.

The next line just increments our counter. We are incrementing by 32 because that's the height of our image. The "+=" operator increments a variable. That is, "x += 32" is equivalent to "x = x +32." The goal is to make a tile of our image on the screen.

It's time to move on to last and final section of Lesson 04. Proceed.

Part Five

Quote :

We're almost finished with our image blitting program. This is the final section Lesson 04. If you haven't read parts one, two, three, and four, go start this tutorial from the beginning.

Next, we add the incrementation for the x, like so:
x += 32;
y = 0;
}
This moves the horizontal placeholder over 32 pixels, the width of our image. So essentially we're moving over one column. Then we set the y placeholder back to zero so it can start from the top of the column again and work its way down.

Now our image is drawn. But wait, there's one more step! Right now the "screen" is only stored in memory. This is because it is much much quicker to write to memory than to write to the screen. So since we're done with our manipulation of the screen, we now need to actually put those changes into effect; this is called flipping the screen.
flipScreen();
}
The flipScreen() function is also defined in graphics.h. Calling it is what actually does the updating of the screen.

And finally, we shut down the program, allowing us to look at our beautiful creation and admire our grid of images.
sceKernelSleepThread();
return 0;
}

So now you have your completed main.c, now we need to compile this baby. The Makefile for this program needs a few slight modifications.
TARGET = hello
OBJS = main.o graphics.o framebuffer.o

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

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

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Image Example

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
It's the standard Makefile, but with two differences. The first is that we have added graphics.o and framebuffer.o to the OBJS line. This is simply because we are using these source files (graphics.c and it uses framebuffer.c). This simply tells the compiler that we need these compiled into our project too. The second thing that we have added are some LIBS, we put in zlib with "-lz" and we added libpng with "-lpng." We also added access to the graphics hardware with "-lpspgu" and then put in the math library (which graphics.h uses) using "-lm." Compile, and there you have it, your first program with images. Now go out and create some great applications and games using your new knowledge!

Note: Be sure that when you put the EBOOT on your PSP you also copy the PNG image file and place it in the same folder as the EBOOT.

Be sure to add the feed to your RSS Aggregator (or Google Homepage, or Firefox Live Bookmark) to stay updated with the latest tutorials.

If you have enjoyed this tutorial and have a spare buck or two, please consider donating to the author. Or, if you have a website, link to this tutorial series (helping spread the word means more homebrew for all!).

If there's a calling, I will consider making more tutorials. Please contact me with your feedback on the tutorials and on what you'd like to see in the next lessons. My AIM is Yeldarb2k3, and my e-mail is Yeldarb [at] Barbdwyer [dot] com. Also, if you are looking for someone to design you a website, please contact me through my site, Barbdwyer Web Design.
Back to top Go down
View user profile
-LeetGamer-
Admin


Posts : 247
Points : 397
Reputation : 4
Join date : 2010-09-29
Age : 25

PostSubject: Re: Starter C/C++ Tutorials   Thu Sep 30, 2010 9:32 am

Lesson 5

Part One

Quote :

Ok, so you've set up the development environment, written your first program, leaned some programming techniques, and dabbled in image programming, but what's next? Well, since you're on this page, I'll bet it comes as no surprise to you that it's Lesson 05! Here we will improve our programming skills (and by "we," I really mean "you") by learning about some more advanced concepts.

Advanced, though, is subjective. We are still forming the groundwork in C that you will build upon in truly advanced applications. By the end of this lesson, you should know how to "overclock" the PSP to its true speed of 333 MHz, be able to write text to the screen (graphic text, not the debug text we used before), and have an understanding of how colors work on the PSP.

The program that we are going to construct in this tutorial is a "backround changer." Basically, we are going to allow the user to select the color of the background, and we are going to change it accordingly, as well as display the components of that color on the screen.

First, some background. There is a wide misconception about "overclocking" the PSP. Because of preconceived notions, people associate "overclocking" with heat issues and broken hardware. There is a myth that "overclocking" the PSP is dangerous to the hardware. This is simply not the case with the PSP. The truth is that the PSP is underclocked when it ships from the factory. There are several theories for why Sony did this. One theory is that it drained battery life too quickly for Sony's liking (for us, that isn't much of a concern; spinning the UMD takes up far more battery power than loading off of the Memory Stick, so we already have a tremendous advantage in terms of battery life). Another theory is that Sony wanted developers to write streamlined code. And the third prevalent theory (and the most likely in my opinion) is that they want to allow developers to use the full speed at some point in the future to give a boost to games that will come out later. Anyway, the PSP normally runs at 222 MHz. If you need more power for your programs, "overclocking" is an option. The program we make here will not need the power per se, but I think it's a good place to introduce the concept.

So here we go, let's start out our program. You'll need to download another zip file for this lesson. You can get it here. You'll need to make a main.c file in the same folder as the files you extract from the zip file.

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

#include "graphics.h"
Assuming you have completed the previous lessons, this isn't anything you haven't seen. The only thing that should look new to you is the "psppower.h" include. This file contains the functions we will use to change the PSP's clock speed.

On to some more familiar code:
PSP_MODULE_INFO("Background Changer", 0, 1, 1);

#define RGB(r, g, b) ((r)|((g)<<8)|((b)<<16))
Remember how in Lesson 02 we just glossed over this line without explaining what it really did? Well, I think it's time that you learn. The first parameter is your program identifier, so basically your program name. The second parameter allows you to pass attributes. For most of your programs you will just want to use a 0, but if you are making a kernel mode app, you will need to switch this to "0x1000". The third parameter is for the major version, the fourth is minor version. These are just meant to document the version number of your program.

Now the standard callbacks:
/* 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;
}
That concludes the set-up portion of this tutorial. Continue on to the second part of this tutorial. Onwards!

Part Two

Quote :

This is the second part of Lesson 05; if you haven't completed the first part, do that now.

So now that we have it all set up, we get to the meat of the program, the main() function.
int main(void) {
scePowerSetClockFrequency(333, 333, 166);
This is the line that sets the clock frequency (as should be evident from the function name). You may be wondering why there are three parameters, though. I mean, there's only one processor, right? Wrong. The PSP actually has three processors. The first sets the CPU (the main processor); this is what most of your programs will be running on. The second parameter is the Media Engine. Last I checked, you could only run MIPS Assembly code on this processor. The Media Engine also runs at 333 MHz. The third parameter controls the Graphics Core. This is what people mean when they talk about using the "GPU." The GPU runs at 166 MHz. The default speeds (if you don't change them yourself) are "222, 222, 111."

Next, we'll set up the screen, this is just like what we did in the last tutorial:
SetupCallbacks();
initGraphics();
Then, since we're going to be accepting input, if you'll remember from Lesson 03, we need to define a variable of type SceCtrlData. For old time's sake, we'll name it "pad."
SceCtrlData pad;
Then we'll set up two more variables and an array:
int i;
int selComponent = 0;
char filler[10];
The integer, "i," will be used in one of our loops later on. The character array is what we will use as a string to ouput some information later in the program. And "selComponent" is what we will use to remember which color component the user is editting.

Next we will declare and initialize three variables that will store the information for our background. A color is composed of three components: Red, Green, and Blue. The maximum value of each in a 32 bit color is 255. Zero of each color is black, 255 of each is white, a combination is anywhere in between. You will sometimes see hex values representing colors. Hex is a base-16 counting system. It goes from 0 to F (F being 16). So, with a 32 bit system, FF would equal 255 (16*16, subtracting one because you start counting at zero). So, white would be "FFFFFF" (255 red, 255 blue, 255 green). Anyway, we'll use three variables to store the background color information:
int bgR = 0;
int bgG = 0;
int bgB = 0;
Our background is now black. Remember, though, this is just storing the information so that we can manipulate it. We won't actually set the screen's background to black until we do something with these variables.

Now, since we are going to be displaying text through functions in the "graphics.h" file rather than by pspDebugScreenPrintf, we need to tell our program what colors we want to use for the text.
Color highlightColor = RGB(200, 200, 200);
Color dimmedColor = RGB(100, 100, 100);
Color shadowColorH = RGB(55, 55, 55 );
Color shadowColorD = RGB(55, 55, 55 );
First of all, I'll explain what exactly these lines are doing. They are using the RGB macro that was explained in Lesson 04 to turn color components into a single color. The "Color" datatype is defined in the "graphics.c" include file. You may also see a u32 (a 32 bit integer) used in some programs to hold a color.

The reason we have four variables is because we want to highlight the component that the user is currently changing. So, we have two main colors for that, one color for the text that is highlighted and one color for the text that is dimmed. Also, since we have a dynamic background (meaning that it can change), we are going to use a shadow. This will help make our text stand out from the background. I tried a few different colors and this is what I ended up with. Feel free to play around with the colors and see if you find anything that looks better.

Now we'll go into our game loop.
while(1) {
sceCtrlReadBufferPositive(&pad, 1);
A standard, infinite while loop and a standard control pad read.

Go to the third part of this tutorial to continue your program.

Part Three

Quote :

This is the third part of Lesson 05; if you haven't completed the first part or the second part do that now.

Now we'll handle that control pad read. What we want to do is have the up and down arrows select which color component the user is editting. We want the left and right arrows to adjust that color.

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();
}
}
This chunk of code does the first half of that. It will decrement the variable if up is pressed (because we want to start from the top, 0 will be the top-most color, 1 will be the middle, and 2 will be the bottom). And it will increment the variable if the down arrow is pressed. The for loops are in there to pause the program for a second when one of the buttons is pressed. This way, it makes it easier for the user to go through the options one at a time, rather than accidentally scrolling too far.

The next code block is what controls the left and right arrows:
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;
}
}
As you look at this code, you're probably asking yourself, "What the *insert naughty word here* is this switch structure?" Well, it's fairly simple. Basically it's like an if/else structure all built into one. It takes a variable, "switch(yourVariable)," and then compares it to several cases that it could be. If it doesn't match any of the cases, then it runs the default case. In our program, the "selComponent" variable should only be 0, 1, or 2, since we limited it to that above. In the top switch structure, if "selComponent" equals 0, our variable "bgR" will be incremented by one. If it equals 1, "bgG" will be incremented by one, and if it equals two, "bgB" will be incremented by one. The break statement exits out of the switch structure.

We're almost done with our program! Keep reading in the fourth part of this tutorial to add toyour program.

Part Four

Quote :

This is the fourth part of Lesson 05; if you haven't completed the first, second, or third part do that now.

So now we have code that allows us to select a color component to modify, and change the variable associated with that color. The next step is to actually display the program on the screen. Our user interface (UI) will consist of text, telling the user what the color components are, and the background.

Recall that the colors can only be from 0-255. We need to make sure that they don't exceed this when the user scrolls through them, so we'll use a series of if/else statements to ensure that they stay within the target range.

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;
}
This should be pretty self explanatory. If the value of any of the components gets out of the range, we just set it to the lowest (or highest) place it should be able to be.

Now we want to fill the background the color that our variables dictate.
fillScreenRect(RGB(bgR, bgG, bgB), 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
"fillScreenRect()" is a function that is defined in "graphics.c." It fills a rectangular portion of the screen a given color. It takes five parameters. The first is the color we want the rectangle to be. The second is the x position of the rectangle. The third is the y position of the rectangle. The fourth is the width of the rectangle. And the fifth is the height of the rectangle.

Now we want to write the text over the background that we just drew:
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);
}
You should remember the "sprintf()" function from Lesson 04. It is the one that parses a "printf()" into a string. This time, though, we are using a variable. We want to display both the color (Red) and the value (bgR). We do this the same way that we outputted an integer in Lesson 03 (with the "%i" modifier). Then, if the component is selected, we use the "printTextScreen()" function from "graphics.c" to print our string to the screen. The function takes four parameters, the first is the x position. The second is the y position. The third is the string. And the fourth is the color. The reason for the if/else statement is that we want to display the text in a different color if it is supposed to be selected. We also outputted the shadow below the text.

We now need to do the same thing for the other two colors.
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);
}
We're nearly done, I promise! In part five we'll put the finishing touches on our program and create our Makefile.

Part Five

Quote :

This is the fifth (and final) part of Lesson 05; if you haven't completed the first, second, third, and fourth parts do that now.

Then we flip the screen and add in a little pause just to control the speed of our program (we don't want it to go too fast). And finally, wrap up our program.

flipScreen();

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

return 0;
}
Now, just create a Makefile, and you are ready to compile.
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
Nothing in the Makefile has been changed since Lesson 04 except for the name and the addition of "-lpsppower," which adds the library associated with overclocking. And there you have it, a Background Changer.

Update: Lesson 06 is now up. The topic, "Adding Sound."

Be sure to add the feed to your RSS Aggregator (or Google Homepage, or Firefox Live Bookmark) to stay updated with the latest tutorials.

If you have enjoyed this tutorial and have a spare buck or two, please consider donating to the author. Or, if you have a website, link to this tutorial series (helping spread the word means more homebrew for all!).

If there's a calling, I will consider making more tutorials. Please contact me with your feedback on the tutorials and on what you'd like to see in the next lessons. My AIM is Yeldarb2k3, and my e-mail is Yeldarb [at] Barbdwyer [dot] com. Also, if you are looking for someone to design you a website, please contact me through my site, Barbdwyer Web Design.
Back to top Go down
View user profile
-LeetGamer-
Admin


Posts : 247
Points : 397
Reputation : 4
Join date : 2010-09-29
Age : 25

PostSubject: Re: Starter C/C++ Tutorials   Thu Sep 30, 2010 9:32 am

Lesson Six

Part One

Quote :

This lesson was written by guest writer Stephen Merity (aka Smerity), so thanks to him for his great contribution.

First of all, thanks goes to John_K for porting libmad to the PSP and for developing PSPMediaCenter (which I used some of the code from). Also, a special thank you to seventoes, who posted a while back on PS2Dev.org asking for help with libmad with code that was so close to working!

This tutorial is a simple walkthrough concerning playing music in your programs. Sound FX and background music are two aspects that give an application a polished feeling, but they are often overlooked. Whether that is because a developer is rushing to get a release out of the door or whether it is because they simply don't know how to implement sound (or have any fitting music to to with their application) is unclear. Hopefully this tutorial will help some people get sound into their programs.

The first thing we are going to have to do is grab libmad from SVN. libmad is an MPEG audio decoder released under the GPL. It has been ported to the PSP by John_K.

To do this, open Cygwin, and type
svn checkout svn://svn.ps2dev.org/psp/trunk/libmad
You should see a long list of filenames scroll by as the package is downloaded.

Now we will switch into the libmad directory and compile the library:
cd libmad
make
The next bit is a little deviation from the routine we used to install our libraries in Lesson 04. Usually, you could type "make install" and it would automatically install the files to their appropriate directories. Unfortunately, libmad's install script appears to be broken at the moment. Not to worry though, we can install it manually ourselves.
cp -Rf ./include /usr/local/pspdev/psp/
cp -Rf ./lib/libmad.a /usr/local/pspdev/psp/lib
NOTE: There is a space between "./include" and "/usr..." and between "libmad.a" and "/usr..."

This will copy all of the files into their appropriate place. The "-Rf" tag stands for "Recursive" and "final" -- it will just make sure that you copy everything and that you won't get any permission errors (which some users have reported as a problem without these flags).

Next, download and extract some necessary files into a new project folder. Inside are two files, mp3player.c and mp3player.h which were obtained from John_K's PSPMediaCenter, I made some slight changes to the files as follows (you don't need to do anything with this, it's just in case you were wondering):
//DO NOT ADD THIS TO YOUR PROGRAM
//IT IS EXAMPLE CODE
mp3player.c
Line 76 - /* void void MP3setStubs to end of function */ - specific to stubs again, see mp3player.h

mp3player.h
Line 10 - #include "../../codec.h" - specific to PSPMediaCenter
Line 17 - void MP3setStubs(codecStubs * stubs); - specific to PSPMediaCenter
Other than that, it was very clean. John_K has done a great job in porting it.

Now, on to the fun part. Create main.c in your editor of choice, and begin with your comments:
// Mp3 Player Sample on PSP
// By *YOUR NAME HERE*
The next little section should be standard to you. The only new includes are the "pspaudio.h" and "pspaudiolib.h." These headers are needed for the audio-specific functions that we will use in our program.
#include <pspkernel.h>
#include <pspctrl.h>
#include <pspdebug.h>
#include <pspaudio.h>
#include <pspaudiolib.h>
#include <psppower.h>

#include "mp3player.h"

PSP_MODULE_INFO("Mp3 Player Example", 0, 1, 1);
#define printf pspDebugScreenPrintf
You will also see that we included one of the files that you downloaded, "mp3player.h" (make sure that it's in the same directory as our source file). We also defined printf and did our PSP_MODULE_INFO.

Continue this tutorial with part two.

Part Two

Quote :

This page is the second page of a lesson written by guest writer Stephen Merity (aka Smerity). If you have stumbled upon this page without going through the first part, go back and start from the beginning.

And now on to what I like to call the twilight zone. I call it that because at this moment, I have no clue how it works or why, but I do intend finding out some day. Anyway, these functions are necessary for your code.

// TWILIGHT ZONE! <do doo do doo>
/* 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;
}
// END OF TWILIGHT ZONE! <do doo do do>
Now onto the main section of your code. First thing we will do is set the PSP's clock speed to full. Please note that this will not damage your PSP in any way, as it has only been underclocked to this speed by Sony, the reason was most likely battery life (for more information, see Lesson 05. Another notable addition is the "pspAudioInit()" function. This is similar to the "pspDebugScreenInit()" function that we have always called. Basically, it sets up the speakers and everything to be ready to handle our sound output.
int main() {
scePowerSetClockFrequency(333, 333, 166);

pspDebugScreenInit();
SetupCallbacks();

pspAudioInit();
SceCtrlData pad;
int i;
Now for the shiny new stuff!
MP3_Init(1);
MP3_Load("test.mp3");
MP3_Play();
MP3_Init() initialises the structures used by libmad and sets which channel the PSP will be playing back on (in this case, Channel 1). MP3_Load() is pretty self descriptive, it loads your MP3 file (either change this to your MP3 filename or change your MP3 to be called "test.mp3"). MP3_Play() starts the sound playing through the speakers.

Next up is part three where we'll continue building our program.

Part Three

Quote :

This page is the third page of a lesson written by guest writer Stephen Merity (aka Smerity). If you have stumbled upon this page without going through the first and second parts, go back and start from the beginning.

The next section shows some options you have, and also acts as a very simple user interface.

while(1) {
sceCtrlReadBufferPositive(&pad, 1);
if(pad.Buttons & PSP_CTRL_CROSS) {
break;
} else if(pad.Buttons & PSP_CTRL_CIRCLE) {
MP3_Pause();
for(i=0; i<10; i++) {
sceDisplayWaitVblankStart();
}
}

if (MP3_EndOfStream() == 1) {
MP3_Stop();
}
}
We read the buttons like we have been doing since Lesson 03. If they push the [X] button, we will exit out of the loop (and effectively, exit out of our program). If the user pushes [O], then we will pause the music using the MP3_Stop() function. Finally, we check the MP3_EndOfStream() function to see if the MP3 file has finished playing. The function will return "1" if it is over and "0" if it's still playing. If it's over, we stop the playback simply so that we're not eating up CPU power when we don't need to.

Then we will enter some wrapup code for after the user exits the loop:
MP3_Stop();
MP3_FreeTune();

sceKernelSleepThread();

return 0;
}
To end our program, we will first stop the MP3, and then release the memory space of the music file we just used. Freeing up memory isn't incredibly important in this program (when the program terminates, the memory will be freed anyway), but it could be important in other homebrew programs. If you don't free the memory, it won't be available for other functions once the MP3 has finished.

So that's it for your C file. Simple, right? Now we move on to the all-important Makefile.

Remember - the Makefile has no suffix (no .exe, .doc, .txt, .tar, etc.)

The main change is the addition of the our new libraries. "lmad" is for linking libmad for decoding the Mp3. "pspaudiolib" and "pspaudio" give our program access to the PSP's audio hardware (the speakers, for instance).
TARGET = mp3
OBJS = mp3player.o main.o
CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
LIBDIR =

LIBS = -lmad -lpspaudiolib -lpspaudio -lpsppower
LDFLAGS =
EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = MP3 Player Example
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
Now all that's left is to go into Cygwin, find your project folder, and type in the magic word, "make" (or for Firmware Version 1.50 type "make kxploit" to generate your two folders).

You will need to copy your "test.mp3" into the folder where your program will be located on the PSP in order for it to be loaded when your program runs. On Firmware Version 1.50, it goes in the folder without the "%" at the end. Be sure that your MP3's bitrate is less than or equal to 160 KBPS or you will get an error (if you do get a "recoverable frame level error (lost synchronization)" error and your sound file still plays, you probably don't need to worry about it).

You can now simply start the application and enjoy your MP3!

Be sure to add the feed to your RSS Aggregator (or Google Homepage, or Firefox Live Bookmark) to stay updated with the latest tutorials.

If you have enjoyed this tutorial and have a spare buck or two, please consider donating to the author. Or, if you have a website, link to this tutorial series (helping spread the word means more homebrew for all!).

Please contact me with your feedback on the tutorials and on what you'd like to see in the next lessons. My e-mail is smerity [at] smerity [dot] com.
Back to top Go down
View user profile
SXYxJeff

avatar

Posts : 47
Points : 55
Reputation : 0
Join date : 2010-09-29

PostSubject: Re: Starter C/C++ Tutorials   Mon Oct 04, 2010 8:48 pm

nice since i dont have my psp atm i think i might try learning some c++
Back to top Go down
View user profile
Sponsored content




PostSubject: Re: Starter C/C++ Tutorials   

Back to top Go down
 
Starter C/C++ Tutorials
Back to top 
Page 1 of 1
 Similar topics
-
» Which starter deck?
» kick starter...
» "Engkol" Kick Starter dah longgar
» Chess Game Starer Kit
» Tutorials - How to add multiple ranks Forumotion

Permissions in this forum:You cannot reply to topics in this forum
PSP Coding :: PSP Programming :: PSP Programming Tutorials :: Homebrew Programming Tutorials-
Jump to: