From 0987b3602b2f4fe6433d0438caf1d1a8c5cf517a Mon Sep 17 00:00:00 2001 From: pyroesp Date: Sun, 28 May 2023 05:04:50 +0200 Subject: [PATCH] add image_display sample to pspsdk fix for PR renamed logo folder to image_display, renamed logo to image in source, changed image used, removed FW version from makefile, added header to source, added image_display to all samples makefile --- src/samples/Makefile.samples | 1 + src/samples/prx/image_display/Makefile.sample | 16 ++ src/samples/prx/image_display/main.c | 212 ++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 src/samples/prx/image_display/Makefile.sample create mode 100644 src/samples/prx/image_display/main.c diff --git a/src/samples/Makefile.samples b/src/samples/Makefile.samples index 67c0d7d9..b7f181cc 100644 --- a/src/samples/Makefile.samples +++ b/src/samples/Makefile.samples @@ -61,6 +61,7 @@ SAMPLES = \ power \ prx/prx_loader \ prx/testprx \ + prx/image_display \ savedata/utility \ savedata/decrypt \ savedata/encrypt \ diff --git a/src/samples/prx/image_display/Makefile.sample b/src/samples/prx/image_display/Makefile.sample new file mode 100644 index 00000000..054a89e5 --- /dev/null +++ b/src/samples/prx/image_display/Makefile.sample @@ -0,0 +1,16 @@ +TARGET = image_display +BUILD_PRX = 1 + +OBJS = main.o + +INCDIR = +CFLAGS = -Os -G0 -Wall +CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti +ASFLAGS = $(CFLAGS) +LIBS = + +LIBDIR = + + +PSPSDK=$(shell psp-config --pspsdk-path) +include $(PSPSDK)/lib/build_prx.mak \ No newline at end of file diff --git a/src/samples/prx/image_display/main.c b/src/samples/prx/image_display/main.c new file mode 100644 index 00000000..82aedf6b --- /dev/null +++ b/src/samples/prx/image_display/main.c @@ -0,0 +1,212 @@ +/* + * PSP Software Development Kit - https://github.com/pspdev + * ----------------------------------------------------------------------- + * Licensed under the BSD license, see LICENSE in PSPSDK root for details. + * + * main.c - image display plugin example + * + * Copyright (c) 2023 pyroesp + * + */ + +#include +#include +#include +#include + + +PSP_MODULE_INFO("image display", PSP_MODULE_USER, 0, 1); +PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER); + + +#define SCREEN_W 480 +#define SCREEN_H 272 + +#define IMAGE_W 72 +#define IMAGE_H 40 +#define PIXEL_PER_BYTE 8 + + +// monochrome 1 bit per pixel image +u8 image[] = { + 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, + 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, + 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, + 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, + 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, + 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, + 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, + 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, + 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, + 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, + 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00 +}; + + +// main thread id +int thid; +// main running flag +int running; + + +// convert 0-359 degree value to u32 ABGR color +u32 color_Wheel(int degrees); + + +// main thread +int main_thread(SceSize args, void *argp){ + u64 tick; + unsigned int* vram32; + int bufferwidth, pixelformat; + + // wait for psp boot + sceKernelDelayThread(10 * 1000 * 1000); + // get psp ticks for pseudo randomness + sceRtcGetCurrentTick(&tick); + + // set image start position from ticks + s16 image_x = tick % (SCREEN_W - IMAGE_W); + s16 image_y = tick % (SCREEN_H - IMAGE_H); + // set image movement from start position + s16 image_vx = (image_x & 1) ? -1 : 1; + s16 image_vy = (image_y & 1) ? -1 : 1; + // image color + u32 image_color = color_Wheel((int)((tick / 1000) % 360)); + + // main menu + while (running){ + // check x collision + if ((image_x + image_vx) >= (SCREEN_W - IMAGE_W) || (image_x + image_vx) <= 0){ + //change direction + image_vx = -image_vx; + // update tick value when changing direction + sceRtcGetCurrentTick(&tick); + // change color based on tick value + image_color = color_Wheel((int)((tick / 1000) % 360)); + } + // check y collision + if ((image_y + image_vy) >= (SCREEN_H - IMAGE_H) || (image_y + image_vy) <= 0){ + //change direction + image_vy = -image_vy; + // update tick value when changing direction + sceRtcGetCurrentTick(&tick); + // change color based on tick value + image_color = color_Wheel((int)((tick / 1000) % 360)); + } + + // move image + image_x += image_vx; + image_y += image_vy; + + + // get vram + int ret = sceDisplayGetFrameBuf((void*)&vram32, &bufferwidth, &pixelformat, PSP_DISPLAY_SETBUF_IMMEDIATE); + // works with both PSP_DISPLAY_SETBUF_NEXTFRAME and PSP_DISPLAY_SETBUF_IMMEDIATE + + // check if return value from sceDisplayGetFrameBuf is valid + // check if vram32 is not NULL + // check if bufferwidth is not 0 + if (ret == 0 && vram32 != NULL && bufferwidth != 0){ + // draw image + for (int i = 0; i < IMAGE_H; i++){ + for (int j = 0; j < IMAGE_W; j++){ + // check if the pixel bit of the image at position 'j' is 1 + if (image[(i * (IMAGE_W / PIXEL_PER_BYTE)) + j / PIXEL_PER_BYTE] & (1 << (PIXEL_PER_BYTE - 1 - (j % PIXEL_PER_BYTE)))){ + // write image to vram + vram32[(image_y + i) * bufferwidth + (image_x + j)] = image_color; + } + } + } + } + // not checking return value and/or vram32 pointer will result in a crash when putting the PSP to sleep + + + // wait for vblank and allow for callbacks + if (sceDisplayWaitVblankStartCB() < 0) + break; // end of VSH ? + } + + return sceKernelExitDeleteThread(0); +} + + + +int module_start(SceSize args, void *argp){ + running = 0; + // create and start main thread + thid = sceKernelCreateThread("image_display", main_thread, 0x10, 4*1024, PSP_THREAD_ATTR_USER, NULL); + if (thid >= 0){ + running = 1; + sceKernelStartThread(thid, args, argp); + } + + return 0; +} + +int module_stop(SceSize args, void *argp){ + // clean exit main thread + if (running){ + running = 0; + SceUInt time = 200*1000; + int ret = sceKernelWaitThreadEnd(thid, &time); + if (ret < 0) + sceKernelTerminateDeleteThread(thid); + } + + return 0; +} + + + +// convert 0-359 degree value to u32 ABGR color +u32 color_Wheel(int degrees){ + u8 red = 0, green = 0, blue = 0; + degrees = degrees % 360; + + if (degrees < 120){ + red = ((120 - degrees) * 255) / 120; + green = (degrees * 255) / 120; + blue = 0; + }else if (degrees < 240){ + degrees -= 120; + red = 0; + green = ((120 - degrees) * 255) / 120; + blue = (degrees * 255) / 120; + }else{ + degrees -= 240; + red = (degrees * 255) / 120; + green = 0; + blue = ((120 - degrees) * 255) / 120; + } + + return (0xFF000000 | blue << 16 | green << 8 | red); +} \ No newline at end of file