diff --git a/_includes/samples/sdl2_image/CMakeLists.txt b/_includes/samples/sdl2_image/CMakeLists.txt new file mode 100644 index 0000000..e3655ed --- /dev/null +++ b/_includes/samples/sdl2_image/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.5) + +project(sdl2-image) + +add_executable(${PROJECT_NAME} main.c) + +include(FindPkgConfig) +pkg_search_module(SDL2 REQUIRED sdl2) +pkg_search_module(SDL2_IMAGE REQUIRED SDL2_image) + +target_include_directories(${PROJECT_NAME} PRIVATE + ${SDL2_INCLUDE_DIRS} + ${SDL2_IMAGE_INCLUDE_DIRS} +) + +target_link_libraries(${PROJECT_NAME} PRIVATE + ${SDL2_LIBRARIES} + ${SDL2_IMAGE_LIBRARIES} +) + +if(PSP) + # Create an EBOOT.PBP file + create_pbp_file( + TARGET ${PROJECT_NAME} + ICON_PATH NULL + BACKGROUND_PATH NULL + PREVIEW_PATH NULL + TITLE ${PROJECT_NAME} + VERSION 01.00 + ) +endif() \ No newline at end of file diff --git a/_includes/samples/sdl2_image/main.c b/_includes/samples/sdl2_image/main.c new file mode 100644 index 0000000..06dd48b --- /dev/null +++ b/_includes/samples/sdl2_image/main.c @@ -0,0 +1,73 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER); + + // Enable png support for SDL2_image + IMG_Init(IMG_INIT_PNG); + + SDL_Window * window = SDL_CreateWindow( + "window", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + 480, + 272, + 0 + ); + + SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + + // Load the texture + SDL_Surface * pixels = IMG_Load("grass.png"); + SDL_Texture * sprite = SDL_CreateTextureFromSurface(renderer, pixels); + SDL_FreeSurface(pixels); + + // Store the dimensions of the texture + SDL_Rect sprite_rect; + SDL_QueryTexture(sprite, NULL, NULL, &sprite_rect.w, &sprite_rect.h); + + // Set the position to draw to in the middle of the screen + sprite_rect.x = 480/2 - sprite_rect.w/2; + sprite_rect.y = 272/2 - sprite_rect.h/2; + + int running = 1; + SDL_Event event; + while (running) { + // Process input + if (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + // End the loop if the programs is being closed + running = 0; + break; + case SDL_CONTROLLERDEVICEADDED: + // Connect a controller when it is connected + SDL_GameControllerOpen(event.cdevice.which); + break; + case SDL_CONTROLLERBUTTONDOWN: + if(event.cbutton.button == SDL_CONTROLLER_BUTTON_START) { + // Close the program if start is pressed + running = 0; + } + break; + } + } + + // Clear the screen + SDL_RenderClear(renderer); + + // Draw a red square + SDL_RenderCopy(renderer, sprite, NULL, &sprite_rect); + + // Draw everything on a white background + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); + SDL_RenderPresent(renderer); + } + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + + return 0; +} \ No newline at end of file diff --git a/_includes/samples/shape/main.c b/_includes/samples/shape/main.c index 9660340..dc0bf6b 100644 --- a/_includes/samples/shape/main.c +++ b/_includes/samples/shape/main.c @@ -2,7 +2,7 @@ #include #include -PSP_MODULE_INFO("gutest", 0, 1, 0); +PSP_MODULE_INFO("shape", 0, 1, 0); PSP_MAIN_THREAD_ATTR(THREAD_ATTR_VFPU | THREAD_ATTR_USER); #define BUFFER_WIDTH 512 @@ -11,9 +11,10 @@ PSP_MAIN_THREAD_ATTR(THREAD_ATTR_VFPU | THREAD_ATTR_USER); #define SCREEN_HEIGHT BUFFER_HEIGHT char list[0x20000] __attribute__((aligned(64))); +int running; int exit_callback(int arg1, int arg2, void *common) { - sceKernelExitGame(); + running = 0; return 0; } @@ -101,7 +102,7 @@ int main() { // Setup the library used for rendering initGu(); - int running = 1; + running = 1; while(running){ startFrame(); diff --git a/_includes/samples/sprite/CMakeLists.txt b/_includes/samples/sprite/CMakeLists.txt new file mode 100644 index 0000000..e69638b --- /dev/null +++ b/_includes/samples/sprite/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.5) + +project(texture) + +add_executable(${PROJECT_NAME} main.c) + +target_link_libraries(${PROJECT_NAME} PRIVATE + pspgu + pspge + pspdisplay +) + +# Create an EBOOT.PBP file +create_pbp_file( + TARGET ${PROJECT_NAME} + ICON_PATH NULL + BACKGROUND_PATH NULL + PREVIEW_PATH NULL + TITLE ${PROJECT_NAME} + VERSION 01.00 +) \ No newline at end of file diff --git a/_includes/samples/sprite/main.c b/_includes/samples/sprite/main.c new file mode 100644 index 0000000..2d2f3c3 --- /dev/null +++ b/_includes/samples/sprite/main.c @@ -0,0 +1,142 @@ +#include +#include +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include + +PSP_MODULE_INFO("texture", 0, 1, 0); +PSP_MAIN_THREAD_ATTR(THREAD_ATTR_VFPU | THREAD_ATTR_USER); + +#define BUFFER_WIDTH 512 +#define BUFFER_HEIGHT 272 +#define SCREEN_WIDTH 480 +#define SCREEN_HEIGHT BUFFER_HEIGHT + +typedef struct +{ + float u, v; + uint32_t colour; + float x, y, z; +} TextureVertex; + +typedef struct +{ + int width, height; + uint32_t * data; +} Texture; + +char list[0x20000] __attribute__((aligned(64))); + +void * fbp0; +void * fbp1; +Texture texture; +int running; + +int exit_callback(int arg1, int arg2, void *common) { + running = 0; + return 0; +} + +int callback_thread(SceSize args, void *argp) { + int cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL); + sceKernelRegisterExitCallback(cbid); + sceKernelSleepThreadCB(); + return 0; +} + +int setup_callbacks(void) { + int thid = sceKernelCreateThread("update_thread", callback_thread, 0x11, 0xFA0, 0, 0); + if(thid >= 0) + sceKernelStartThread(thid, 0, 0); + return thid; +} + +void initGu(){ + sceGuInit(); + + fbp0 = guGetStaticVramBuffer(BUFFER_WIDTH, BUFFER_HEIGHT, GU_PSM_8888); + fbp1 = guGetStaticVramBuffer(BUFFER_WIDTH, BUFFER_HEIGHT, GU_PSM_8888); + + //Set up buffers + sceGuStart(GU_DIRECT, list); + sceGuDrawBuffer(GU_PSM_8888, fbp0, BUFFER_WIDTH); + sceGuDispBuffer(SCREEN_WIDTH,SCREEN_HEIGHT,fbp1, BUFFER_WIDTH); + + // We do not care about the depth buffer in this example + sceGuDepthBuffer(fbp0, 0); // Set depth buffer to a length of 0 + sceGuDisable(GU_DEPTH_TEST); // Disable depth testing + + //Set up viewport + sceGuOffset(2048 - (SCREEN_WIDTH / 2), 2048 - (SCREEN_HEIGHT / 2)); + sceGuViewport(2048, 2048, SCREEN_WIDTH, SCREEN_HEIGHT); + sceGuEnable(GU_SCISSOR_TEST); + sceGuScissor(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + // Start a new frame and enable the display + sceGuFinish(); + sceGuDisplay(GU_TRUE); +} + +void endGu(){ + sceGuDisplay(GU_FALSE); + sceGuTerm(); +} + +void startFrame(){ + sceGuStart(GU_DIRECT, list); + sceGuClearColor(0xFFFFFFFF); // White background + sceGuClear(GU_COLOR_BUFFER_BIT); +} + +void endFrame(){ + sceGuFinish(); + sceGuSync(0, 0); + sceDisplayWaitVblankStart(); + sceGuSwapBuffers(); +} + +void drawTexture(float x, float y, float w, float h) { + static TextureVertex vertices[2]; + + vertices[0].u = 0.0f; + vertices[0].v = 0.0f; + vertices[0].colour = 0xFFFFFFFF; + vertices[0].x = x; + vertices[0].y = y; + vertices[0].z = 0.0f; + + vertices[1].u = w; + vertices[1].v = h; + vertices[1].colour = 0xFFFFFFFF; + vertices[1].x = x + w; + vertices[1].y = y + h; + vertices[1].z = 0.0f; + + sceGuTexMode(GU_PSM_8888, 0, 0, GU_FALSE); + sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB); + sceGuTexImage(0, texture.width, texture.height, texture.width, texture.data); + + sceGuEnable(GU_TEXTURE_2D); + sceGuDrawArray(GU_SPRITES, GU_COLOR_8888 | GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D, 2, 0, vertices); + sceGuDisable(GU_TEXTURE_2D); +} + + +int main() { + initGu(); + + texture.data = (uint32_t *) stbi_load("grass.png", &texture.width, &texture.height, NULL, 4); + + running = 1; + while(running){ + startFrame(); + + drawTexture(SCREEN_WIDTH / 2 - 8, SCREEN_HEIGHT / 2 - 8, 16, 16); + + endFrame(); + } + + return 0; +} \ No newline at end of file diff --git a/basic_programs.md b/basic_programs.md index 2dfdfca..d7b2d3b 100644 --- a/basic_programs.md +++ b/basic_programs.md @@ -84,6 +84,45 @@ More libgu examples can be found + +View source + +**main.c** + +```c +{% include samples/sprite/main.c %} +``` + +**CMakeLists.txt** + +```cmake +{% include samples/sprite/CMakeLists.txt %} +``` + +Building can be done with: + +```shell +mkdir build && cd build +psp-cmake .. +make +``` + +This will result in an EBOOT.PBP file in the build directory. Put it in a directory in ms0:/PSP/GAME/ and add the grass image file, download it from here, to be able to run it on the PSP. + +More libgu examples can be found here. + + + ## Controller {: .fs-6 .fw-700 } @@ -209,6 +248,56 @@ More documentation on SDL can be found + +View source + +**main.c** + +```c +{% include samples/sdl2_image/main.c %} +``` + +**CMakeLists.txt** + +```cmake +{% include samples/sdl2_image/CMakeLists.txt %} +``` + +Building can be done with: + +```shell +mkdir build && cd build +psp-cmake .. +make +``` + +This will result in an EBOOT.PBP file in the build directory. Put it in a directory in ms0:/PSP/GAME/ and add the grass image file, download it from here, to be able to run it on the PSP. + +If you have sdl2 sdl2-image dev packages and a compiler installed this code will also build on Linux for Linux by running: + +```shell +mkdir build && cd build +cmake .. +make +``` + +Documentation for SDL2_image can be found here. + + + + ## Using SDL2 mixer {: .fs-6 .fw-700 } @@ -244,6 +333,8 @@ make This will result in an EBOOT.PBP file in the build directory. Put it in a directory in ms0:/PSP/GAME/ and you need an audio file to test the program, download it from here. Put it in a directory in ms0:/MUSIC/ and then rename the audio file same as name on your *MUSIC_PATH* macro in your C code and the PSP can run it. +Documentation for SDL2_mixer can be found here. + ## Using SDL2 ttf @@ -281,6 +372,8 @@ make This will result in an EBOOT.PBP file in the build directory. Put it in a directory in ms0:/PSP/GAME/ and you need a font file to test the program, download it from here. Put it in a directory same as EBOOT.PBP and the PSP can run it. +Documentation for SDL2_ttf can be found here. + ## More Examples diff --git a/resources/grass.png b/resources/grass.png new file mode 100644 index 0000000..9f8471a Binary files /dev/null and b/resources/grass.png differ