welcome to part one of my new tutorial series on programming for the Vita, where we will be laying the groundwork for you to develop your own homebrew / port games to the vita! Today we will be doing a graphical hello world with the unofficial VitaSDK and vita2dlib.
Requirements:
- Vita with Henkaku
********************************************************************************************************************
- Unofficial VitaSDK and vita2dlib installed on a linux system (see mylast tutorial)
********************************************************************************************************************
- Local Area Network connectivity between Vita and linux system
********************************************************************************************************************
So, don't be scared but here comes a dump of code. Scroll a little bit down for the explanation.
Main.c
Code: Select all
#include <psp2/display.h>
#include <psp2/moduleinfo.h>
#include <psp2/kernel/processmgr.h>
#include <vita2d.h>
PSP2_MODULE_INFO(0, 0, "HelloWorld");
int main() {
vita2d_pgf *pgf;
vita2d_init();
vita2d_set_clear_color(RGBA8(0, 0, 0, 255));
pgf = vita2d_load_default_pgf();
while(1){
vita2d_start_drawing();
vita2d_clear_screen();
vita2d_pgf_draw_text(pgf, 700, 30, RGBA8(0, 255, 0, 255), 1.0f, "Hello, World!");
vita2d_end_drawing();
vita2d_swap_buffers();
}
vita2d_fini();
vita2d_free_pgf(pgf);
sceKernelExitProcess(0);
return 0;
}
First of all, let's look at the include directives (for example the "#include <psp2/display.h>" directive).
These include directives, also called preprocessor directives, because they are enumerated into files on a "preparation" pass, basically just tell the C compiler to include (e.g. copy) the contents of this header file (display.h) into the file being compiled (our file main.c in this case). With our Vita, also called an embedded linux device, we use these include directives to use functions specific to some aspect of the hardware / software. For example, if we do "#include <psp2/ctrl.h>", we want access to controller-related functions, variables, enums (a new variable type documented in the header and defined in source), and so forth, so we can for example do a bitwise AND ("&" in C) with our own subset variable of type SceCtrlData called "pad.buttons" and the controller state of the UP directional button, which is called "SCE_CTRL_UP".
********************************************************************************************************************
Now, before we dive into the skeletal function calls of a Vita program, we have to define how a function routine is created / defined in C and also, how to then call it. So, let's assume we have a system capable of running assembled C code in a stable manner as well as capable of printing printf() calls to the standard output, which is presumptuously a terminal. Here's how the creation and calling of a function in the same file would work:
example.c:
Code: Select all
#include <stdio.h>
// Creation of function routine
int printdec(int decimal){
printf("%d", decimal);
return 0;
}
int main(){
// Function call
printdec(123);
return 0;
}
Code: Select all
[variable type you want to return] [function name]([function arguments]){
[routine]
}
Code: Select all
[function name]([function arguments]);
********************************************************************************************************************
Now we can look at the first skeletal function call in Vita program, namely
Code: Select all
PSP2_MODULE_INFO(0, 0, "HelloWorld");
- 1. The attribute (No idea what that is)
- 2. The version of your program
- 3. Your program name. This has a maximum length of 27 characters.
********************************************************************************************************************
Next up:
Code: Select all
int main(){
********************************************************************************************************************
Following, we have:
Code: Select all
vita2d_pgf *pgf;
********************************************************************************************************************
Code: Select all
vita2d_init();
********************************************************************************************************************
Code: Select all
vita2d_set_clear_color(RGBA8(0, 0, 0, 255));
So, first of all, we have the function call vita2d_set_clear_color() which sets the color the vita should display when the screen is cleared of all to be rendered elements.
Inside that, as the colour argument, we have the RGBA8() macro, which is defined (we'll get to that in part 2) in vita2dlib. Basically, this macro allows you to specify colours.
Here, we can specify the Red, Green, Blue and Alpha values, the max of every single value being 255, and the min 0.
The Red value specifies the amount of red, the Green value the amount of green and so on.
But what does the alpha value specify??
Well, that value specifies the opacity of the object, so how little transparency there is: 255 is no transparency and 0 is all transparent.
********************************************************************************************************************
Code: Select all
pgf = vita2d_load_default_pgf();
********************************************************************************************************************
Code: Select all
while(1){
********************************************************************************************************************
Code: Select all
vita2d_start_drawing();
[!Important]But, we won't see anything on the vita screen until we call vita2d_swap_buffers();[/!Important]
Because then, our instructions will be swapped to the vita memory allocated to the display and the display controller will then execute the instructions.
********************************************************************************************************************
Code: Select all
vita2d_clear_screen();
Remember vita2d_set_clear_color() and RGBA8()?
********************************************************************************************************************
Code: Select all
vita2d_pgf_draw_text(pgf, 700, 30, RGBA8(0, 255, 0, 255), 1.0f, "Hello World!");
The arguments to the function are in following order:
- 1. Assigned pointer of type vita2d_pgf
- 2. X coordinate of start of text
- 3. Y coordinate of start of text
- 4. Colour value created with the RGBA8 macro
- 5. Value for the size of text of type float (e.g with decimal points)
- 6. String to display
********************************************************************************************************************
Code: Select all
vita2d_end_drawing();
********************************************************************************************************************
Code: Select all
vita2d_swap_buffers();
********************************************************************************************************************
Code: Select all
}
********************************************************************************************************************
Code: Select all
vita2d_fini();
********************************************************************************************************************
Code: Select all
vita2d_free_pgf(pgf);
********************************************************************************************************************
Code: Select all
sceKernelExitProcess(0);
********************************************************************************************************************
Code: Select all
return 0;
This is standard programming practice in C.
Makefile:
Code: Select all
TITLE_ID = VITA2DTST
TARGET = vita2dsample
OBJS = main.o
LIBS = -lvita2d -lSceKernel_stub -lSceDisplay_stub -lSceGxm_stub \
-lSceSysmodule_stub -lSceCtrl_stub -lScePgf_stub \
-lSceCommonDialog_stub -lfreetype -lpng -ljpeg -lz -lm -lc
PREFIX = arm-vita-eabi
CC = $(PREFIX)-gcc
CFLAGS = -Wl,-q -Wall -O3
ASFLAGS = $(CFLAGS)
all: $(TARGET).vpk
%.vpk: eboot.bin
vita-mksfoex -s TITLE_ID=$(TITLE_ID) "$(TARGET)" param.sfo
eboot.bin: $(TARGET).velf
vita-make-fself $< $@
%.velf: %.elf
vita-elf-create $< $@
$(TARGET).elf: $(OBJS)
$(CC) $(CFLAGS) $^ $(LIBS) -o $@
%.o: %.png
$(PREFIX)-ld -r -b binary -o $@ $^
clean:
@rm -rf $(TARGET).vpk $(TARGET).velf $(TARGET).elf $(OBJS) \
eboot.bin param.sfo
Compilation of our Hello World program:
1. Copy the code of main.c and Makefile and put them in two seperate files with their equivalent names.
2. Open a terminal, change your directory to that of the two files and run:
Code: Select all
make
1. Open molecularshell on your vita and press select
2. Open a terminal and type:
Code: Select all
cd ~
wget https://github.com/xyzz/Vita_Doom/releases/download/1.0/vitadoom.vpk
ftp [ip displayed on your vita] [port displayed on your vita] (without the brackets)
put ~/vitadoom.vpk /ux0:vitadoom.vpk
4. Press select again
5. Open a terminal and type:
Code: Select all
ftp [ip displayed on your vita] [port displayed on your vita] (without the brackets)
put path/to/eboot.bin /ux0:app/DOOM00000/eboot.bin
put path/to/param.sfo /ux0:app/DOOM00000/sce_sys/param.sfo
7. ???
8. Profit!!!
See you in the next part!