├── .gitignore ├── .gitmodules ├── 1-Context ├── gl │ ├── Makefile │ └── context.c └── sceGu │ ├── Makefile │ └── context.c ├── 2-Drawing ├── gl │ ├── Makefile │ └── triangle.c ├── img.png └── sceGu │ ├── Makefile │ └── triangle.c ├── 3-Textures ├── gl │ ├── Makefile │ ├── circle.png │ ├── container.jpg │ └── texture.c ├── img.png └── sceGu │ ├── Makefile │ ├── circle.png │ ├── container.jpg │ └── texture.c ├── 4-Camera ├── gl │ ├── Makefile │ ├── camera.c │ ├── circle.png │ └── container.jpg ├── img.png └── sceGu │ ├── Makefile │ ├── camera.c │ ├── circle.png │ └── container.jpg ├── 5-Sprites ├── gl │ ├── Makefile │ ├── circle.png │ ├── container.jpg │ └── sprites.c ├── img.png └── sceGu │ ├── Makefile │ ├── circle.png │ ├── container.jpg │ └── sprites.c ├── 6-Tilemaps ├── gl │ ├── Makefile │ ├── default.png │ ├── terrain.png │ └── tilemaps.c ├── img.png └── sceGu │ ├── Makefile │ ├── default.png │ ├── terrain.png │ └── tilemaps.c ├── LICENSE ├── README.md └── common ├── callbacks.c ├── callbacks.h ├── common-gl.c ├── common-gl.h ├── common-sce.c ├── common-sce.h └── stb_image.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | 54 | .vscode 55 | *.PBP 56 | *.SFO 57 | *.prx -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "gu2gl"] 2 | path = gu2gl 3 | url = https://github.com/IridescentRose/gu2gl.git 4 | -------------------------------------------------------------------------------- /1-Context/gl/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = context 2 | OBJS = context.o ../../common/callbacks.o 3 | 4 | INCDIR = ../../gu2gl/ 5 | CFLAGS = -Wall 6 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 7 | ASFLAGS = $(CFLAGS) 8 | 9 | LIBDIR = 10 | LDFLAGS = 11 | LIBS= -lpspgum -lpspgu 12 | 13 | EXTRA_TARGETS = EBOOT.PBP 14 | PSP_EBOOT_TITLE = Basic Context 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build.mak -------------------------------------------------------------------------------- /1-Context/gl/context.c: -------------------------------------------------------------------------------- 1 | #include "../../common/callbacks.h" 2 | #define GUGL_IMPLEMENTATION 3 | #include 4 | 5 | // PSP Module Info 6 | PSP_MODULE_INFO("Context Sample", 0, 1, 1); 7 | PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU); 8 | 9 | // Global variables 10 | int running = 1; 11 | static unsigned int __attribute__((aligned(16))) list[262144]; 12 | 13 | int main() { 14 | // Boilerplate 15 | SetupCallbacks(); 16 | 17 | // Initialize Graphics 18 | guglInit(list); 19 | 20 | //Main program loop 21 | while(running){ 22 | guglStartFrame(list, GL_FALSE); 23 | 24 | //Clear background to Green 25 | glClearColor(0xFF00FF00); 26 | glClear(GL_COLOR_BUFFER_BIT); 27 | 28 | guglSwapBuffers(GL_TRUE, GL_FALSE); 29 | } 30 | 31 | // Terminate Graphics 32 | guglTerm(); 33 | 34 | // Exit Game 35 | sceKernelExitGame(); 36 | return 0; 37 | } -------------------------------------------------------------------------------- /1-Context/sceGu/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = context 2 | OBJS = context.o ../../common/callbacks.o 3 | 4 | INCDIR = ../../gu2gl/ 5 | CFLAGS = -Wall 6 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 7 | ASFLAGS = $(CFLAGS) 8 | 9 | LIBDIR = 10 | LDFLAGS = 11 | LIBS= -lpspgum -lpspgu 12 | 13 | EXTRA_TARGETS = EBOOT.PBP 14 | PSP_EBOOT_TITLE = Basic Context 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build.mak -------------------------------------------------------------------------------- /1-Context/sceGu/context.c: -------------------------------------------------------------------------------- 1 | #include "../../common/callbacks.h" 2 | 3 | // Include Graphics Libraries 4 | #include 5 | #include 6 | #include 7 | 8 | // PSP Module Info 9 | 10 | PSP_MODULE_INFO("Context Sample", 0, 1, 1); 11 | PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU); 12 | 13 | // Define PSP Width / Height 14 | #define PSP_BUF_WIDTH (512) 15 | #define PSP_SCR_WIDTH (480) 16 | #define PSP_SCR_HEIGHT (272) 17 | 18 | // Global variables 19 | int running = 1; 20 | static unsigned int __attribute__((aligned(16))) list[262144]; 21 | 22 | // Get Memory Size 23 | static unsigned int getMemorySize(unsigned int width, unsigned int height, unsigned int psm) 24 | { 25 | switch (psm) 26 | { 27 | case GU_PSM_T4: 28 | return (width * height) >> 1; 29 | 30 | case GU_PSM_T8: 31 | return width * height; 32 | 33 | case GU_PSM_5650: 34 | case GU_PSM_5551: 35 | case GU_PSM_4444: 36 | case GU_PSM_T16: 37 | return 2 * width * height; 38 | 39 | case GU_PSM_8888: 40 | case GU_PSM_T32: 41 | return 4 * width * height; 42 | 43 | default: 44 | return 0; 45 | } 46 | } 47 | 48 | // Vram Buffer Request 49 | void* getStaticVramBuffer(unsigned int width, unsigned int height, unsigned int psm) 50 | { 51 | static unsigned int staticOffset = 0; 52 | unsigned int memSize = getMemorySize(width,height,psm); 53 | void* result = (void*)staticOffset; 54 | staticOffset += memSize; 55 | 56 | return result; 57 | } 58 | 59 | // Vram Texture Request 60 | void* getStaticVramTexture(unsigned int width, unsigned int height, unsigned int psm) 61 | { 62 | void* result = getStaticVramBuffer(width,height,psm); 63 | return (void*)(((unsigned int)result) + ((unsigned int)sceGeEdramGetAddr())); 64 | } 65 | 66 | 67 | // Initialize Graphics 68 | void initGraphics() { 69 | void* fbp0 = getStaticVramBuffer(PSP_BUF_WIDTH,PSP_SCR_HEIGHT,GU_PSM_8888); 70 | void* fbp1 = getStaticVramBuffer(PSP_BUF_WIDTH,PSP_SCR_HEIGHT,GU_PSM_8888); 71 | void* zbp = getStaticVramBuffer(PSP_BUF_WIDTH,PSP_SCR_HEIGHT,GU_PSM_4444); 72 | 73 | sceGuInit(); 74 | 75 | sceGuStart(GU_DIRECT,list); 76 | sceGuDrawBuffer(GU_PSM_8888,fbp0,PSP_BUF_WIDTH); 77 | sceGuDispBuffer(PSP_SCR_WIDTH,PSP_SCR_HEIGHT,fbp1,PSP_BUF_WIDTH); 78 | sceGuDepthBuffer(zbp,PSP_BUF_WIDTH); 79 | sceGuOffset(2048 - (PSP_SCR_WIDTH/2),2048 - (PSP_SCR_HEIGHT/2)); 80 | sceGuViewport(2048,2048,PSP_SCR_WIDTH,PSP_SCR_HEIGHT); 81 | sceGuDepthRange(65535,0); 82 | sceGuScissor(0,0,PSP_SCR_WIDTH,PSP_SCR_HEIGHT); 83 | sceGuEnable(GU_SCISSOR_TEST); 84 | sceGuDepthFunc(GU_GEQUAL); 85 | sceGuEnable(GU_DEPTH_TEST); 86 | sceGuFrontFace(GU_CW); 87 | sceGuShadeModel(GU_SMOOTH); 88 | sceGuEnable(GU_CULL_FACE); 89 | sceGuEnable(GU_TEXTURE_2D); 90 | sceGuEnable(GU_CLIP_PLANES); 91 | sceGuFinish(); 92 | sceGuSync(0,0); 93 | 94 | sceDisplayWaitVblankStart(); 95 | sceGuDisplay(GU_TRUE); 96 | } 97 | 98 | // Start Frame 99 | void startFrame() { 100 | sceGuStart(GU_DIRECT, list); 101 | } 102 | 103 | // End Frame 104 | void endFrame() { 105 | sceGuFinish(); 106 | sceGuSync(0, 0); 107 | sceDisplayWaitVblankStart(); 108 | sceGuSwapBuffers(); 109 | } 110 | 111 | // End Graphics 112 | void termGraphics() { 113 | sceGuTerm(); 114 | } 115 | 116 | int main() { 117 | // Boilerplate 118 | SetupCallbacks(); 119 | 120 | // Initialize Graphics 121 | initGraphics(); 122 | 123 | 124 | //Main program loop 125 | while(running){ 126 | startFrame(); 127 | 128 | //Clear background to Green 129 | sceGuClearColor(0xFF00FF00); 130 | sceGuClear(GU_COLOR_BUFFER_BIT); 131 | 132 | endFrame(); 133 | } 134 | 135 | // Terminate Graphics 136 | termGraphics(); 137 | 138 | // Exit Game 139 | sceKernelExitGame(); 140 | return 0; 141 | } -------------------------------------------------------------------------------- /2-Drawing/gl/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = triangle 2 | OBJS = triangle.o ../../common/callbacks.o 3 | 4 | INCDIR = ../../gu2gl/ 5 | CFLAGS = -Wall 6 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 7 | ASFLAGS = $(CFLAGS) 8 | 9 | LIBDIR = 10 | LDFLAGS = 11 | LIBS= -lpspgum -lpspgu 12 | 13 | EXTRA_TARGETS = EBOOT.PBP 14 | PSP_EBOOT_TITLE = Triangle Sample 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build.mak -------------------------------------------------------------------------------- /2-Drawing/gl/triangle.c: -------------------------------------------------------------------------------- 1 | #include "../../common/callbacks.h" 2 | #define GUGL_IMPLEMENTATION 3 | #include 4 | 5 | // PSP Module Info 6 | PSP_MODULE_INFO("Triangle Sample", 0, 1, 1); 7 | PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU); 8 | 9 | // Global variables 10 | int running = 1; 11 | static unsigned int __attribute__((aligned(16))) list[262144]; 12 | 13 | struct Vertex 14 | { 15 | unsigned int color; 16 | float x, y, z; 17 | }; 18 | 19 | struct Vertex __attribute__((aligned(16))) triangle[3] = { 20 | {0xFF00FF00, 0.35f, 0.0, -1.0f}, 21 | {0xFF0000FF, -0.35f, 0.0, -1.0f}, 22 | {0xFFFF0000, 0.0, 0.5f, -1.0f}, 23 | }; 24 | 25 | struct Vertex __attribute__((aligned(16))) square[6] = { 26 | {0xFF00FF00, -0.25f, -0.25f, -1.0f}, 27 | {0xFF0000FF, -0.25f, 0.25f, -1.0f}, 28 | {0xFFFF0000, 0.25f, 0.25f, -1.0f}, 29 | 30 | {0xFFFF0000, 0.25f, 0.25f, -1.0f}, 31 | {0xFFFFFFFF, 0.25f, -0.25f, -1.0f}, 32 | {0xFF00FF00, -0.25f, -0.25f, -1.0f}, 33 | }; 34 | 35 | struct Vertex __attribute__((aligned(16))) square_indexed[4] = { 36 | {0xFF00FFFF, -0.25f, -0.25f, -1.0f}, 37 | {0xFFFF00FF, -0.25f, 0.25f, -1.0f}, 38 | {0xFFFFFF00, 0.25f, 0.25f, -1.0f}, 39 | {0xFF000000, 0.25f, -0.25f, -1.0f}, 40 | }; 41 | 42 | unsigned short __attribute__((aligned(16))) indices[6] = { 43 | 0, 1, 2, 2, 3, 0 44 | }; 45 | 46 | /** 47 | * @brief Resets matrix and applies transform 48 | * 49 | */ 50 | void reset_transform(float x, float y, float z){ 51 | ScePspFVector3 v = {x, y, z}; 52 | glLoadIdentity(); 53 | gluTranslate(&v); 54 | } 55 | 56 | int main() { 57 | // Boilerplate 58 | SetupCallbacks(); 59 | 60 | // Initialize Graphics 61 | guglInit(list); 62 | 63 | // Initialize Matrices 64 | glMatrixMode(GL_PROJECTION); 65 | glLoadIdentity(); 66 | glOrtho(-16.0f / 9.0f, 16.0f / 9.0f, -1.0f, 1.0f, -10.0f, 10.0f); 67 | 68 | glMatrixMode(GL_VIEW); 69 | glLoadIdentity(); 70 | 71 | glMatrixMode(GL_MODEL); 72 | glLoadIdentity(); 73 | 74 | //Main program loop 75 | while(running){ 76 | guglStartFrame(list, GL_FALSE); 77 | 78 | // We're doing a 2D, Non-Textured render 79 | glDisable(GL_DEPTH_TEST); 80 | glDisable(GL_TEXTURE_2D); 81 | 82 | //Clear background to Bjack 83 | glClearColor(0xFF000000); 84 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 85 | 86 | //Move this left 87 | reset_transform(-0.5f, 0.0f, 0.0f); 88 | 89 | // Draw Triangle 90 | glDrawElements(GL_TRIANGLES, GL_COLOR_8888 | GL_VERTEX_32BITF | GL_TRANSFORM_3D, 3, NULL, triangle); 91 | 92 | //Move back to origin, and right 0.5f, up 0.25f 93 | reset_transform(0.5f, 0.25f, 0.0f); 94 | 95 | // Draw Square 96 | glDrawElements(GL_TRIANGLES, GL_COLOR_8888 | GL_VERTEX_32BITF | GL_TRANSFORM_3D, 6, NULL, square); 97 | 98 | //Move back to origin, and down 0.5f 99 | reset_transform(0.0f, -0.5f, 0.0f); 100 | 101 | // Draw Indexed Square 102 | glDrawElements(GL_TRIANGLES, GL_INDEX_16BIT | GL_COLOR_8888 | GL_VERTEX_32BITF | GL_TRANSFORM_3D, 6, indices, square_indexed); 103 | 104 | guglSwapBuffers(GL_TRUE, GL_FALSE); 105 | } 106 | 107 | // Terminate Graphics 108 | guglTerm(); 109 | 110 | // Exit Game 111 | sceKernelExitGame(); 112 | return 0; 113 | } -------------------------------------------------------------------------------- /2-Drawing/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/2-Drawing/img.png -------------------------------------------------------------------------------- /2-Drawing/sceGu/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = triangle 2 | OBJS = triangle.o ../../common/callbacks.o 3 | 4 | INCDIR = ../../gu2gl/ 5 | CFLAGS = -Wall 6 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 7 | ASFLAGS = $(CFLAGS) 8 | 9 | LIBDIR = 10 | LDFLAGS = 11 | LIBS= -lpspgum -lpspgu 12 | 13 | EXTRA_TARGETS = EBOOT.PBP 14 | PSP_EBOOT_TITLE = Triangle Sample 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build.mak -------------------------------------------------------------------------------- /2-Drawing/sceGu/triangle.c: -------------------------------------------------------------------------------- 1 | #include "../../common/callbacks.h" 2 | 3 | // Include Graphics Libraries 4 | #include 5 | #include 6 | #include 7 | 8 | // Define PSP Width / Height 9 | #define PSP_BUF_WIDTH (512) 10 | #define PSP_SCR_WIDTH (480) 11 | #define PSP_SCR_HEIGHT (272) 12 | 13 | // PSP Module Info 14 | PSP_MODULE_INFO("Triangle Sample", 0, 1, 1); 15 | PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU); 16 | 17 | // Global variables 18 | int running = 1; 19 | static unsigned int __attribute__((aligned(16))) list[262144]; 20 | 21 | 22 | // Get Memory Size 23 | static unsigned int getMemorySize(unsigned int width, unsigned int height, unsigned int psm) 24 | { 25 | switch (psm) 26 | { 27 | case GU_PSM_T4: 28 | return (width * height) >> 1; 29 | 30 | case GU_PSM_T8: 31 | return width * height; 32 | 33 | case GU_PSM_5650: 34 | case GU_PSM_5551: 35 | case GU_PSM_4444: 36 | case GU_PSM_T16: 37 | return 2 * width * height; 38 | 39 | case GU_PSM_8888: 40 | case GU_PSM_T32: 41 | return 4 * width * height; 42 | 43 | default: 44 | return 0; 45 | } 46 | } 47 | 48 | // Vram Buffer Request 49 | void* getStaticVramBuffer(unsigned int width, unsigned int height, unsigned int psm) 50 | { 51 | static unsigned int staticOffset = 0; 52 | unsigned int memSize = getMemorySize(width,height,psm); 53 | void* result = (void*)staticOffset; 54 | staticOffset += memSize; 55 | 56 | return result; 57 | } 58 | 59 | // Vram Texture Request 60 | void* getStaticVramTexture(unsigned int width, unsigned int height, unsigned int psm) 61 | { 62 | void* result = getStaticVramBuffer(width,height,psm); 63 | return (void*)(((unsigned int)result) + ((unsigned int)sceGeEdramGetAddr())); 64 | } 65 | 66 | 67 | // Initialize Graphics 68 | void initGraphics() { 69 | void* fbp0 = getStaticVramBuffer(PSP_BUF_WIDTH,PSP_SCR_HEIGHT,GU_PSM_8888); 70 | void* fbp1 = getStaticVramBuffer(PSP_BUF_WIDTH,PSP_SCR_HEIGHT,GU_PSM_8888); 71 | void* zbp = getStaticVramBuffer(PSP_BUF_WIDTH,PSP_SCR_HEIGHT,GU_PSM_4444); 72 | 73 | sceGuInit(); 74 | 75 | sceGuStart(GU_DIRECT,list); 76 | sceGuDrawBuffer(GU_PSM_8888,fbp0,PSP_BUF_WIDTH); 77 | sceGuDispBuffer(PSP_SCR_WIDTH,PSP_SCR_HEIGHT,fbp1,PSP_BUF_WIDTH); 78 | sceGuDepthBuffer(zbp,PSP_BUF_WIDTH); 79 | sceGuOffset(2048 - (PSP_SCR_WIDTH/2),2048 - (PSP_SCR_HEIGHT/2)); 80 | sceGuViewport(2048,2048,PSP_SCR_WIDTH,PSP_SCR_HEIGHT); 81 | sceGuDepthRange(65535,0); 82 | sceGuScissor(0,0,PSP_SCR_WIDTH,PSP_SCR_HEIGHT); 83 | sceGuEnable(GU_SCISSOR_TEST); 84 | sceGuDepthFunc(GU_GEQUAL); 85 | sceGuEnable(GU_DEPTH_TEST); 86 | sceGuFrontFace(GU_CW); 87 | sceGuShadeModel(GU_SMOOTH); 88 | sceGuEnable(GU_CULL_FACE); 89 | sceGuEnable(GU_TEXTURE_2D); 90 | sceGuEnable(GU_CLIP_PLANES); 91 | sceGuFinish(); 92 | sceGuSync(0,0); 93 | 94 | sceDisplayWaitVblankStart(); 95 | sceGuDisplay(GU_TRUE); 96 | } 97 | 98 | // Start Frame 99 | void startFrame() { 100 | sceGuStart(GU_DIRECT, list); 101 | } 102 | 103 | // End Frame 104 | void endFrame() { 105 | sceGuFinish(); 106 | sceGuSync(0, 0); 107 | sceDisplayWaitVblankStart(); 108 | sceGuSwapBuffers(); 109 | } 110 | 111 | // End Graphics 112 | void termGraphics() { 113 | sceGuTerm(); 114 | } 115 | 116 | // Vert Data 117 | struct Vertex 118 | { 119 | unsigned int color; 120 | float x, y, z; 121 | }; 122 | 123 | struct Vertex __attribute__((aligned(16))) triangle[3] = { 124 | {0xFF00FF00, 0.35f, 0.0, -1.0f}, 125 | {0xFF0000FF, -0.35f, 0.0, -1.0f}, 126 | {0xFFFF0000, 0.0, 0.5f, -1.0f}, 127 | }; 128 | 129 | struct Vertex __attribute__((aligned(16))) square[6] = { 130 | {0xFF00FF00, -0.25f, -0.25f, -1.0f}, 131 | {0xFF0000FF, -0.25f, 0.25f, -1.0f}, 132 | {0xFFFF0000, 0.25f, 0.25f, -1.0f}, 133 | 134 | {0xFFFF0000, 0.25f, 0.25f, -1.0f}, 135 | {0xFFFFFFFF, 0.25f, -0.25f, -1.0f}, 136 | {0xFF00FF00, -0.25f, -0.25f, -1.0f}, 137 | }; 138 | 139 | struct Vertex __attribute__((aligned(16))) square_indexed[4] = { 140 | {0xFF00FFFF, -0.25f, -0.25f, -1.0f}, 141 | {0xFFFF00FF, -0.25f, 0.25f, -1.0f}, 142 | {0xFFFFFF00, 0.25f, 0.25f, -1.0f}, 143 | {0xFF000000, 0.25f, -0.25f, -1.0f}, 144 | }; 145 | 146 | unsigned short __attribute__((aligned(16))) indices[6] = { 147 | 0, 1, 2, 2, 3, 0 148 | }; 149 | 150 | /** 151 | * @brief Resets matrix and applies transform 152 | * 153 | */ 154 | void reset_transform(float x, float y, float z){ 155 | ScePspFVector3 v = {x, y, z}; 156 | sceGumLoadIdentity(); 157 | sceGumTranslate(&v); 158 | } 159 | 160 | int main() { 161 | // Boilerplate 162 | SetupCallbacks(); 163 | 164 | // Initialize Graphics 165 | initGraphics(); 166 | 167 | // Initialize Matrices 168 | sceGumMatrixMode(GU_PROJECTION); 169 | sceGumLoadIdentity(); 170 | sceGumOrtho(-16.0f / 9.0f, 16.0f / 9.0f, -1.0f, 1.0f, -10.0f, 10.0f); 171 | 172 | sceGumMatrixMode(GU_VIEW); 173 | sceGumLoadIdentity(); 174 | 175 | sceGumMatrixMode(GU_MODEL); 176 | sceGumLoadIdentity(); 177 | 178 | //Main program loop 179 | while(running){ 180 | startFrame(); 181 | 182 | // We're doing a 2D, Non-Textured render 183 | sceGuDisable(GU_DEPTH_TEST); 184 | sceGuDisable(GU_TEXTURE_2D); 185 | 186 | //Clear background to Bjack 187 | sceGuClearColor(0xFF000000); 188 | sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT | GU_STENCIL_BUFFER_BIT); 189 | 190 | //Move this left 191 | reset_transform(-0.5f, 0.0f, 0.0f); 192 | 193 | // Draw Triangle 194 | sceGumDrawArray(GU_TRIANGLES, GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 3, NULL, triangle); 195 | 196 | //Move back to origin, and right 0.5f, up 0.25f 197 | reset_transform(0.5f, 0.25f, 0.0f); 198 | 199 | // Draw Square 200 | sceGumDrawArray(GU_TRIANGLES, GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 6, NULL, square); 201 | 202 | //Move back to origin, and down 0.5f 203 | reset_transform(0.0f, -0.5f, 0.0f); 204 | 205 | // Draw Indexed Square 206 | sceGumDrawArray(GU_TRIANGLES, GU_INDEX_16BIT | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 6, indices, square_indexed); 207 | 208 | endFrame(); 209 | } 210 | 211 | // Terminate Graphics 212 | termGraphics(); 213 | 214 | // Exit Game 215 | sceKernelExitGame(); 216 | return 0; 217 | } -------------------------------------------------------------------------------- /3-Textures/gl/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = texture 2 | OBJS = texture.o ../../common/callbacks.o 3 | 4 | INCDIR = ../../gu2gl/ 5 | CFLAGS = -Wall -std=c11 6 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 7 | ASFLAGS = $(CFLAGS) 8 | 9 | LIBDIR = 10 | LDFLAGS = 11 | LIBS= -lpspgum -lpspgu -lm 12 | 13 | EXTRA_TARGETS = EBOOT.PBP 14 | PSP_EBOOT_TITLE = Texture Sample 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build.mak -------------------------------------------------------------------------------- /3-Textures/gl/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/3-Textures/gl/circle.png -------------------------------------------------------------------------------- /3-Textures/gl/container.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/3-Textures/gl/container.jpg -------------------------------------------------------------------------------- /3-Textures/gl/texture.c: -------------------------------------------------------------------------------- 1 | #include "../../common/callbacks.h" 2 | 3 | #define STB_IMAGE_IMPLEMENTATION 4 | #include "../../common/stb_image.h" 5 | 6 | #include 7 | #include 8 | 9 | #define GUGL_IMPLEMENTATION 10 | #include 11 | 12 | 13 | // PSP Module Info 14 | PSP_MODULE_INFO("Texture Sample", 0, 1, 1); 15 | PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU); 16 | 17 | // Global variables 18 | int running = 1; 19 | static unsigned int __attribute__((aligned(16))) list[262144]; 20 | 21 | struct Vertex 22 | { 23 | float u, v; 24 | unsigned int color; 25 | float x, y, z; 26 | }; 27 | 28 | struct Vertex __attribute__((aligned(16))) square_indexed[4] = { 29 | {0.0f, 0.0f, 0xFF00FFFF, -0.25f, -0.25f, -1.0f}, 30 | {1.0f, 0.0f, 0xFFFF00FF, -0.25f, 0.25f, -1.0f}, 31 | {1.0f, 1.0f, 0xFFFFFF00, 0.25f, 0.25f, -1.0f}, 32 | {0.0f, 1.0f, 0xFF000000, 0.25f, -0.25f, -1.0f}, 33 | }; 34 | 35 | unsigned short __attribute__((aligned(16))) indices[6] = { 36 | 0, 1, 2, 2, 3, 0 37 | }; 38 | 39 | void swizzle_fast(u8 *out, const u8 *in, const unsigned int width, const unsigned int height) { 40 | unsigned int blockx, blocky; 41 | unsigned int j; 42 | 43 | unsigned int width_blocks = (width / 16); 44 | unsigned int height_blocks = (height / 8); 45 | 46 | unsigned int src_pitch = (width - 16) / 4; 47 | unsigned int src_row = width * 8; 48 | 49 | const u8 *ysrc = in; 50 | u32 *dst = (u32 *)out; 51 | 52 | for (blocky = 0; blocky < height_blocks; ++blocky) { 53 | const u8 *xsrc = ysrc; 54 | for (blockx = 0; blockx < width_blocks; ++blockx) { 55 | const u32 *src = (u32 *)xsrc; 56 | for (j = 0; j < 8; ++j) { 57 | *(dst++) = *(src++); 58 | *(dst++) = *(src++); 59 | *(dst++) = *(src++); 60 | *(dst++) = *(src++); 61 | src += src_pitch; 62 | } 63 | xsrc += 16; 64 | } 65 | ysrc += src_row; 66 | } 67 | } 68 | 69 | unsigned int pow2(const unsigned int value) { 70 | unsigned int poweroftwo = 1; 71 | while (poweroftwo < value) { 72 | poweroftwo <<= 1; 73 | } 74 | return poweroftwo; 75 | } 76 | 77 | void copy_texture_data(void* dest, const void* src, const int pW, const int width, const int height){ 78 | for (unsigned int y = 0; y < height; y++) { 79 | for (unsigned int x = 0; x < width; x++) { 80 | ((unsigned int*)dest)[x + y * pW] = ((unsigned int *)src)[x + y * width]; 81 | } 82 | } 83 | } 84 | 85 | typedef struct { 86 | unsigned int width, height; 87 | unsigned int pW, pH; 88 | void* data; 89 | }Texture; 90 | 91 | Texture* load_texture(const char* filename, const int vram) { 92 | int width, height, nrChannels; 93 | stbi_set_flip_vertically_on_load(GL_TRUE); 94 | unsigned char *data = stbi_load(filename, &width, &height, 95 | &nrChannels, STBI_rgb_alpha); 96 | 97 | if(!data) 98 | return NULL; 99 | 100 | Texture* tex = (Texture*)malloc(sizeof(Texture)); 101 | tex->width = width; 102 | tex->height = height; 103 | tex->pW = pow2(width); 104 | tex->pH = pow2(height); 105 | 106 | unsigned int *dataBuffer = 107 | (unsigned int *)memalign(16, tex->pH * tex->pW * 4); 108 | 109 | // Copy to Data Buffer 110 | copy_texture_data(dataBuffer, data, tex->pW, tex->width, tex->height); 111 | 112 | // Free STB Data 113 | stbi_image_free(data); 114 | 115 | unsigned int* swizzled_pixels = NULL; 116 | size_t size = tex->pH * tex->pW * 4; 117 | if(vram){ 118 | swizzled_pixels = getStaticVramTexture(tex->pW, tex->pH, GU_PSM_8888); 119 | } else { 120 | swizzled_pixels = (unsigned int *)memalign(16, size); 121 | } 122 | 123 | swizzle_fast((u8*)swizzled_pixels, (const u8*)dataBuffer, tex->pW * 4, tex->pH); 124 | 125 | free(dataBuffer); 126 | tex->data = swizzled_pixels; 127 | 128 | sceKernelDcacheWritebackInvalidateAll(); 129 | 130 | return tex; 131 | } 132 | 133 | void bind_texture(Texture* tex) { 134 | if(tex == NULL) 135 | return; 136 | 137 | glTexMode(GU_PSM_8888, 0, 0, 1); 138 | glTexFunc(GL_TFX_MODULATE, GL_TCC_RGBA); 139 | glTexFilter(GL_NEAREST, GL_NEAREST); 140 | glTexWrap(GL_REPEAT, GL_REPEAT); 141 | glTexImage(0, tex->pW, tex->pH, tex->pW, tex->data); 142 | } 143 | 144 | void reset_transform(float x, float y, float z){ 145 | ScePspFVector3 v = {x, y, z}; 146 | glLoadIdentity(); 147 | gluTranslate(&v); 148 | } 149 | 150 | int main() { 151 | // Boilerplate 152 | SetupCallbacks(); 153 | 154 | // Initialize Graphics 155 | guglInit(list); 156 | 157 | // Initialize Matrices 158 | glMatrixMode(GL_PROJECTION); 159 | glLoadIdentity(); 160 | glOrtho(-16.0f / 9.0f, 16.0f / 9.0f, -1.0f, 1.0f, -10.0f, 10.0f); 161 | 162 | glMatrixMode(GL_VIEW); 163 | glLoadIdentity(); 164 | 165 | glMatrixMode(GL_MODEL); 166 | glLoadIdentity(); 167 | 168 | Texture* texture = load_texture("container.jpg", GL_TRUE); 169 | if(!texture) 170 | goto cleanup; 171 | 172 | Texture* texture2 = load_texture("circle.png", GL_TRUE); 173 | if(!texture) 174 | goto cleanup; 175 | 176 | //Main program loop 177 | while(running){ 178 | guglStartFrame(list, GL_FALSE); 179 | 180 | // We're doing a 2D, Textured render 181 | glDisable(GL_DEPTH_TEST); 182 | 183 | // Blending 184 | glBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); 185 | glEnable(GL_BLEND); 186 | 187 | //Clear background to Bjack 188 | glClearColor(0xFF000000); 189 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 190 | 191 | reset_transform(-0.5f, 0.0f, 0.0f); 192 | bind_texture(texture); 193 | 194 | // Draw Indexed Square 195 | glDrawElements(GL_TRIANGLES, GL_INDEX_16BIT | GL_TEXTURE_32BITF | GL_COLOR_8888 | GL_VERTEX_32BITF | GL_TRANSFORM_3D, 6, indices, square_indexed); 196 | 197 | reset_transform(0.5f, 0.0f, 0.0f); 198 | bind_texture(texture2); 199 | 200 | glDrawElements(GL_TRIANGLES, GL_INDEX_16BIT | GL_TEXTURE_32BITF | GL_COLOR_8888 | GL_VERTEX_32BITF | GL_TRANSFORM_3D, 6, indices, square_indexed); 201 | 202 | guglSwapBuffers(GL_TRUE, GL_FALSE); 203 | } 204 | 205 | cleanup: 206 | 207 | // Terminate Graphics 208 | guglTerm(); 209 | 210 | // Exit Game 211 | sceKernelExitGame(); 212 | return 0; 213 | } -------------------------------------------------------------------------------- /3-Textures/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/3-Textures/img.png -------------------------------------------------------------------------------- /3-Textures/sceGu/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = texture 2 | OBJS = texture.o ../../common/callbacks.o 3 | 4 | INCDIR = ../../gu2gl/ 5 | CFLAGS = -Wall -std=c11 6 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 7 | ASFLAGS = $(CFLAGS) 8 | 9 | LIBDIR = 10 | LDFLAGS = 11 | LIBS= -lpspgum -lpspgu -lm 12 | 13 | EXTRA_TARGETS = EBOOT.PBP 14 | PSP_EBOOT_TITLE = Texture Sample 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build.mak -------------------------------------------------------------------------------- /3-Textures/sceGu/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/3-Textures/sceGu/circle.png -------------------------------------------------------------------------------- /3-Textures/sceGu/container.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/3-Textures/sceGu/container.jpg -------------------------------------------------------------------------------- /3-Textures/sceGu/texture.c: -------------------------------------------------------------------------------- 1 | #include "../../common/callbacks.h" 2 | 3 | // Include Graphics Libraries 4 | #include 5 | #include 6 | #include 7 | 8 | #define STB_IMAGE_IMPLEMENTATION 9 | #include "../../common/stb_image.h" 10 | 11 | #include 12 | #include 13 | 14 | // Define PSP Width / Height 15 | #define PSP_BUF_WIDTH (512) 16 | #define PSP_SCR_WIDTH (480) 17 | #define PSP_SCR_HEIGHT (272) 18 | 19 | // PSP Module Info 20 | PSP_MODULE_INFO("Texture Sample", 0, 1, 1); 21 | PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU); 22 | 23 | // sceGuobal variables 24 | int running = 1; 25 | static unsigned int __attribute__((aligned(16))) list[262144]; 26 | 27 | // Get Memory Size 28 | static unsigned int getMemorySize(unsigned int width, unsigned int height, unsigned int psm) 29 | { 30 | switch (psm) 31 | { 32 | case GU_PSM_T4: 33 | return (width * height) >> 1; 34 | 35 | case GU_PSM_T8: 36 | return width * height; 37 | 38 | case GU_PSM_5650: 39 | case GU_PSM_5551: 40 | case GU_PSM_4444: 41 | case GU_PSM_T16: 42 | return 2 * width * height; 43 | 44 | case GU_PSM_8888: 45 | case GU_PSM_T32: 46 | return 4 * width * height; 47 | 48 | default: 49 | return 0; 50 | } 51 | } 52 | 53 | // Vram Buffer Request 54 | void* getStaticVramBuffer(unsigned int width, unsigned int height, unsigned int psm) 55 | { 56 | static unsigned int staticOffset = 0; 57 | unsigned int memSize = getMemorySize(width,height,psm); 58 | void* result = (void*)staticOffset; 59 | staticOffset += memSize; 60 | 61 | return result; 62 | } 63 | 64 | // Vram Texture Request 65 | void* getStaticVramTexture(unsigned int width, unsigned int height, unsigned int psm) 66 | { 67 | void* result = getStaticVramBuffer(width,height,psm); 68 | return (void*)(((unsigned int)result) + ((unsigned int)sceGeEdramGetAddr())); 69 | } 70 | 71 | 72 | // Initialize Graphics 73 | void initGraphics() { 74 | void* fbp0 = getStaticVramBuffer(PSP_BUF_WIDTH,PSP_SCR_HEIGHT,GU_PSM_8888); 75 | void* fbp1 = getStaticVramBuffer(PSP_BUF_WIDTH,PSP_SCR_HEIGHT,GU_PSM_8888); 76 | void* zbp = getStaticVramBuffer(PSP_BUF_WIDTH,PSP_SCR_HEIGHT,GU_PSM_4444); 77 | 78 | sceGuInit(); 79 | 80 | sceGuStart(GU_DIRECT,list); 81 | sceGuDrawBuffer(GU_PSM_8888,fbp0,PSP_BUF_WIDTH); 82 | sceGuDispBuffer(PSP_SCR_WIDTH,PSP_SCR_HEIGHT,fbp1,PSP_BUF_WIDTH); 83 | sceGuDepthBuffer(zbp,PSP_BUF_WIDTH); 84 | sceGuOffset(2048 - (PSP_SCR_WIDTH/2),2048 - (PSP_SCR_HEIGHT/2)); 85 | sceGuViewport(2048,2048,PSP_SCR_WIDTH,PSP_SCR_HEIGHT); 86 | sceGuDepthRange(65535,0); 87 | sceGuScissor(0,0,PSP_SCR_WIDTH,PSP_SCR_HEIGHT); 88 | sceGuEnable(GU_SCISSOR_TEST); 89 | sceGuDepthFunc(GU_GEQUAL); 90 | sceGuEnable(GU_DEPTH_TEST); 91 | sceGuFrontFace(GU_CW); 92 | sceGuShadeModel(GU_SMOOTH); 93 | sceGuEnable(GU_CULL_FACE); 94 | sceGuEnable(GU_TEXTURE_2D); 95 | sceGuEnable(GU_CLIP_PLANES); 96 | sceGuFinish(); 97 | sceGuSync(0,0); 98 | 99 | sceDisplayWaitVblankStart(); 100 | sceGuDisplay(GU_TRUE); 101 | } 102 | 103 | // Start Frame 104 | void startFrame() { 105 | sceGuStart(GU_DIRECT, list); 106 | } 107 | 108 | // End Frame 109 | void endFrame() { 110 | sceGuFinish(); 111 | sceGuSync(0, 0); 112 | sceDisplayWaitVblankStart(); 113 | sceGuSwapBuffers(); 114 | } 115 | 116 | // End Graphics 117 | void termGraphics() { 118 | sceGuTerm(); 119 | } 120 | 121 | struct Vertex 122 | { 123 | float u, v; 124 | unsigned int color; 125 | float x, y, z; 126 | }; 127 | 128 | struct Vertex __attribute__((aligned(16))) square_indexed[4] = { 129 | {0.0f, 0.0f, 0xFF00FFFF, -0.25f, -0.25f, -1.0f}, 130 | {1.0f, 0.0f, 0xFFFF00FF, -0.25f, 0.25f, -1.0f}, 131 | {1.0f, 1.0f, 0xFFFFFF00, 0.25f, 0.25f, -1.0f}, 132 | {0.0f, 1.0f, 0xFF000000, 0.25f, -0.25f, -1.0f}, 133 | }; 134 | 135 | unsigned short __attribute__((aligned(16))) indices[6] = { 136 | 0, 1, 2, 2, 3, 0 137 | }; 138 | 139 | void swizzle_fast(u8 *out, const u8 *in, const unsigned int width, const unsigned int height) { 140 | unsigned int blockx, blocky; 141 | unsigned int j; 142 | 143 | unsigned int width_blocks = (width / 16); 144 | unsigned int height_blocks = (height / 8); 145 | 146 | unsigned int src_pitch = (width - 16) / 4; 147 | unsigned int src_row = width * 8; 148 | 149 | const u8 *ysrc = in; 150 | u32 *dst = (u32 *)out; 151 | 152 | for (blocky = 0; blocky < height_blocks; ++blocky) { 153 | const u8 *xsrc = ysrc; 154 | for (blockx = 0; blockx < width_blocks; ++blockx) { 155 | const u32 *src = (u32 *)xsrc; 156 | for (j = 0; j < 8; ++j) { 157 | *(dst++) = *(src++); 158 | *(dst++) = *(src++); 159 | *(dst++) = *(src++); 160 | *(dst++) = *(src++); 161 | src += src_pitch; 162 | } 163 | xsrc += 16; 164 | } 165 | ysrc += src_row; 166 | } 167 | } 168 | 169 | unsigned int pow2(const unsigned int value) { 170 | unsigned int poweroftwo = 1; 171 | while (poweroftwo < value) { 172 | poweroftwo <<= 1; 173 | } 174 | return poweroftwo; 175 | } 176 | 177 | void copy_texture_data(void* dest, const void* src, const int pW, const int width, const int height){ 178 | for (unsigned int y = 0; y < height; y++) { 179 | for (unsigned int x = 0; x < width; x++) { 180 | ((unsigned int*)dest)[x + y * pW] = ((unsigned int *)src)[x + y * width]; 181 | } 182 | } 183 | } 184 | 185 | typedef struct { 186 | unsigned int width, height; 187 | unsigned int pW, pH; 188 | void* data; 189 | }Texture; 190 | 191 | Texture* load_texture(const char* filename, const int vram) { 192 | int width, height, nrChannels; 193 | stbi_set_flip_vertically_on_load(GU_TRUE); 194 | unsigned char *data = stbi_load(filename, &width, &height, 195 | &nrChannels, STBI_rgb_alpha); 196 | 197 | if(!data) 198 | return NULL; 199 | 200 | Texture* tex = (Texture*)malloc(sizeof(Texture)); 201 | tex->width = width; 202 | tex->height = height; 203 | tex->pW = pow2(width); 204 | tex->pH = pow2(height); 205 | 206 | unsigned int *dataBuffer = 207 | (unsigned int *)memalign(16, tex->pH * tex->pW * 4); 208 | 209 | // Copy to Data Buffer 210 | copy_texture_data(dataBuffer, data, tex->pW, tex->width, tex->height); 211 | 212 | // Free STB Data 213 | stbi_image_free(data); 214 | 215 | unsigned int* swizzled_pixels = NULL; 216 | size_t size = tex->pH * tex->pW * 4; 217 | if(vram){ 218 | swizzled_pixels = getStaticVramTexture(tex->pW, tex->pH, GU_PSM_8888); 219 | } else { 220 | swizzled_pixels = (unsigned int *)memalign(16, size); 221 | } 222 | 223 | swizzle_fast((u8*)swizzled_pixels, (const u8*)dataBuffer, tex->pW * 4, tex->pH); 224 | 225 | free(dataBuffer); 226 | tex->data = swizzled_pixels; 227 | 228 | sceKernelDcacheWritebackInvalidateAll(); 229 | 230 | return tex; 231 | } 232 | 233 | void bind_texture(Texture* tex) { 234 | if(tex == NULL) 235 | return; 236 | 237 | sceGuTexMode(GU_PSM_8888, 0, 0, 1); 238 | sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA); 239 | sceGuTexFilter(GU_NEAREST, GU_NEAREST); 240 | sceGuTexWrap(GU_REPEAT, GU_REPEAT); 241 | sceGuTexImage(0, tex->pW, tex->pH, tex->pW, tex->data); 242 | } 243 | 244 | void reset_transform(float x, float y, float z){ 245 | ScePspFVector3 v = {x, y, z}; 246 | sceGumLoadIdentity(); 247 | sceGumTranslate(&v); 248 | } 249 | 250 | int main() { 251 | // Boilerplate 252 | SetupCallbacks(); 253 | 254 | // Initialize Graphics 255 | initGraphics(); 256 | 257 | // Initialize Matrices 258 | sceGumMatrixMode(GU_PROJECTION); 259 | sceGumLoadIdentity(); 260 | sceGumOrtho(-16.0f / 9.0f, 16.0f / 9.0f, -1.0f, 1.0f, -10.0f, 10.0f); 261 | 262 | sceGumMatrixMode(GU_VIEW); 263 | sceGumLoadIdentity(); 264 | 265 | sceGumMatrixMode(GU_MODEL); 266 | sceGumLoadIdentity(); 267 | 268 | Texture* texture = load_texture("container.jpg", GU_TRUE); 269 | if(!texture) 270 | goto cleanup; 271 | 272 | Texture* texture2 = load_texture("circle.png", GU_TRUE); 273 | if(!texture) 274 | goto cleanup; 275 | 276 | //Main program loop 277 | while(running){ 278 | startFrame(); 279 | 280 | // We're doing a 2D, Textured render 281 | sceGuDisable(GU_DEPTH_TEST); 282 | 283 | // Blending 284 | sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); 285 | sceGuEnable(GU_BLEND); 286 | 287 | //Clear background to Bjack 288 | sceGuClearColor(0xFF000000); 289 | sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT | GU_STENCIL_BUFFER_BIT); 290 | 291 | reset_transform(-0.5f, 0.0f, 0.0f); 292 | bind_texture(texture); 293 | 294 | // Draw Indexed Square 295 | sceGumDrawArray(GU_TRIANGLES, GU_INDEX_16BIT | GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 6, indices, square_indexed); 296 | 297 | reset_transform(0.5f, 0.0f, 0.0f); 298 | bind_texture(texture2); 299 | 300 | sceGumDrawArray(GU_TRIANGLES, GU_INDEX_16BIT | GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 6, indices, square_indexed); 301 | 302 | endFrame(); 303 | } 304 | 305 | cleanup: 306 | 307 | // Terminate Graphics 308 | termGraphics(); 309 | 310 | // Exit Game 311 | sceKernelExitGame(); 312 | return 0; 313 | } -------------------------------------------------------------------------------- /4-Camera/gl/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = camera 2 | OBJS = camera.o ../../common/callbacks.o ../../common/common-gl.o 3 | 4 | INCDIR = ../../gu2gl/ 5 | CFLAGS = -Wall -std=c11 6 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 7 | ASFLAGS = $(CFLAGS) 8 | 9 | LIBDIR = 10 | LDFLAGS = 11 | LIBS= -lpspgum -lpspgu -lm 12 | 13 | EXTRA_TARGETS = EBOOT.PBP 14 | PSP_EBOOT_TITLE = Camera Sample 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build.mak -------------------------------------------------------------------------------- /4-Camera/gl/camera.c: -------------------------------------------------------------------------------- 1 | #include "../../common/callbacks.h" 2 | #include "../../common/common-gl.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // PSP Module Info 9 | PSP_MODULE_INFO("Camera Sample", 0, 1, 1); 10 | PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU); 11 | 12 | // Global variables 13 | int running = 1; 14 | static unsigned int __attribute__((aligned(16))) list[262144]; 15 | 16 | Vertex __attribute__((aligned(16))) square_indexed[4] = { 17 | {0.0f, 0.0f, 0xFF00FFFF, -0.25f, -0.25f, -1.0f}, 18 | {1.0f, 0.0f, 0xFFFF00FF, -0.25f, 0.25f, -1.0f}, 19 | {1.0f, 1.0f, 0xFFFFFF00, 0.25f, 0.25f, -1.0f}, 20 | {0.0f, 1.0f, 0xFF000000, 0.25f, -0.25f, -1.0f}, 21 | }; 22 | 23 | unsigned short __attribute__((aligned(16))) indices[6] = { 24 | 0, 1, 2, 2, 3, 0 25 | }; 26 | 27 | typedef struct{ 28 | float x, y; 29 | float rot; 30 | } Camera2D; 31 | 32 | void apply_camera(const Camera2D* cam){ 33 | glMatrixMode(GL_VIEW); 34 | glLoadIdentity(); 35 | 36 | ScePspFVector3 v = {cam->x, cam->y, 0}; 37 | gluTranslate(&v); 38 | gluRotateZ(cam->rot / 180.0f * 3.14159f); 39 | 40 | glMatrixMode(GL_MODEL); 41 | glLoadIdentity(); 42 | } 43 | 44 | int main() { 45 | // Boilerplate 46 | SetupCallbacks(); 47 | 48 | // Initialize Graphics 49 | guglInit(list); 50 | 51 | // Initialize Matrices 52 | glMatrixMode(GL_PROJECTION); 53 | glLoadIdentity(); 54 | glOrtho(-16.0f / 9.0f, 16.0f / 9.0f, -1.0f, 1.0f, -10.0f, 10.0f); 55 | 56 | glMatrixMode(GL_VIEW); 57 | glLoadIdentity(); 58 | 59 | glMatrixMode(GL_MODEL); 60 | glLoadIdentity(); 61 | 62 | Texture* texture = load_texture("container.jpg", GL_TRUE, GL_TRUE); 63 | if(!texture) 64 | goto cleanup; 65 | 66 | Texture* texture2 = load_texture("circle.png", GL_TRUE, GL_TRUE); 67 | if(!texture) 68 | goto cleanup; 69 | 70 | Camera2D camera = { 71 | .x = 0, 72 | .y = 0, 73 | .rot = 45.0f 74 | }; 75 | 76 | //Main program loop 77 | while(running){ 78 | guglStartFrame(list, GL_FALSE); 79 | 80 | // We're doing a 2D, Textured render 81 | glDisable(GL_DEPTH_TEST); 82 | 83 | // Blending 84 | glBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); 85 | glEnable(GL_BLEND); 86 | 87 | //Clear background to Bjack 88 | glClearColor(0xFF000000); 89 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 90 | 91 | apply_camera(&camera); 92 | 93 | reset_transform(-0.5f, 0.0f, 0.0f); 94 | bind_texture(texture); 95 | 96 | // Draw Indexed Square 97 | glDrawElements(GL_TRIANGLES, GL_INDEX_16BIT | GL_TEXTURE_32BITF | GL_COLOR_8888 | GL_VERTEX_32BITF | GL_TRANSFORM_3D, 6, indices, square_indexed); 98 | 99 | reset_transform(0.5f, 0.0f, 0.0f); 100 | bind_texture(texture2); 101 | 102 | glDrawElements(GL_TRIANGLES, GL_INDEX_16BIT | GL_TEXTURE_32BITF | GL_COLOR_8888 | GL_VERTEX_32BITF | GL_TRANSFORM_3D, 6, indices, square_indexed); 103 | 104 | guglSwapBuffers(GL_TRUE, GL_FALSE); 105 | 106 | camera.rot += 1.0f; 107 | camera.y = sinf(camera.rot / 180.0f) / 2.0f; 108 | } 109 | 110 | cleanup: 111 | 112 | // Terminate Graphics 113 | guglTerm(); 114 | 115 | // Exit Game 116 | sceKernelExitGame(); 117 | return 0; 118 | } -------------------------------------------------------------------------------- /4-Camera/gl/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/4-Camera/gl/circle.png -------------------------------------------------------------------------------- /4-Camera/gl/container.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/4-Camera/gl/container.jpg -------------------------------------------------------------------------------- /4-Camera/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/4-Camera/img.png -------------------------------------------------------------------------------- /4-Camera/sceGu/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = camera 2 | OBJS = camera.o ../../common/callbacks.o ../../common/common-sce.o 3 | 4 | INCDIR = ../../gu2gl/ 5 | CFLAGS = -Wall -std=c11 6 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 7 | ASFLAGS = $(CFLAGS) 8 | 9 | LIBDIR = 10 | LDFLAGS = 11 | LIBS= -lpspgum -lpspgu -lm 12 | 13 | EXTRA_TARGETS = EBOOT.PBP 14 | PSP_EBOOT_TITLE = Camera Sample 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build.mak -------------------------------------------------------------------------------- /4-Camera/sceGu/camera.c: -------------------------------------------------------------------------------- 1 | #include "../../common/callbacks.h" 2 | #include "../../common/common-sce.h" 3 | 4 | // Include Graphics Libraries 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // PSP Module Info 11 | PSP_MODULE_INFO("Camera Sample", 0, 1, 1); 12 | PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU); 13 | 14 | // sceGuobal variables 15 | int running = 1; 16 | static unsigned int __attribute__((aligned(16))) list[262144]; 17 | 18 | Vertex __attribute__((aligned(16))) square_indexed[4] = { 19 | {0.0f, 0.0f, 0xFF00FFFF, -0.25f, -0.25f, -1.0f}, 20 | {1.0f, 0.0f, 0xFFFF00FF, -0.25f, 0.25f, -1.0f}, 21 | {1.0f, 1.0f, 0xFFFFFF00, 0.25f, 0.25f, -1.0f}, 22 | {0.0f, 1.0f, 0xFF000000, 0.25f, -0.25f, -1.0f}, 23 | }; 24 | 25 | unsigned short __attribute__((aligned(16))) indices[6] = { 26 | 0, 1, 2, 2, 3, 0 27 | }; 28 | 29 | 30 | typedef struct{ 31 | float x, y; 32 | float rot; 33 | } Camera2D; 34 | 35 | void apply_camera(const Camera2D* cam){ 36 | sceGumMatrixMode(GU_VIEW); 37 | sceGumLoadIdentity(); 38 | 39 | ScePspFVector3 v = {cam->x, cam->y, 0}; 40 | sceGumTranslate(&v); 41 | sceGumRotateZ(cam->rot / 180.0f * 3.14159f); 42 | 43 | sceGumMatrixMode(GU_MODEL); 44 | sceGumLoadIdentity(); 45 | } 46 | 47 | int main() { 48 | // Boilerplate 49 | SetupCallbacks(); 50 | 51 | // Initialize Graphics 52 | initGraphics(list); 53 | 54 | // Initialize Matrices 55 | sceGumMatrixMode(GU_PROJECTION); 56 | sceGumLoadIdentity(); 57 | sceGumOrtho(-16.0f / 9.0f, 16.0f / 9.0f, -1.0f, 1.0f, -10.0f, 10.0f); 58 | 59 | sceGumMatrixMode(GU_VIEW); 60 | sceGumLoadIdentity(); 61 | 62 | sceGumMatrixMode(GU_MODEL); 63 | sceGumLoadIdentity(); 64 | 65 | Texture* texture = load_texture("container.jpg", GU_TRUE, GU_TRUE); 66 | if(!texture) 67 | goto cleanup; 68 | 69 | Texture* texture2 = load_texture("circle.png", GU_TRUE, GU_TRUE); 70 | if(!texture) 71 | goto cleanup; 72 | 73 | Camera2D camera = { 74 | .x = 0, 75 | .y = 0, 76 | .rot = 45.0f 77 | }; 78 | 79 | //Main program loop 80 | while(running){ 81 | startFrame(list); 82 | 83 | // We're doing a 2D, Textured render 84 | sceGuDisable(GU_DEPTH_TEST); 85 | 86 | // Blending 87 | sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); 88 | sceGuEnable(GU_BLEND); 89 | 90 | //Clear background to Bjack 91 | sceGuClearColor(0xFF000000); 92 | sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT | GU_STENCIL_BUFFER_BIT); 93 | 94 | apply_camera(&camera); 95 | 96 | reset_transform(-0.5f, 0.0f, 0.0f); 97 | bind_texture(texture); 98 | 99 | // Draw Indexed Square 100 | sceGumDrawArray(GU_TRIANGLES, GU_INDEX_16BIT | GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 6, indices, square_indexed); 101 | 102 | reset_transform(0.5f, 0.0f, 0.0f); 103 | bind_texture(texture2); 104 | 105 | sceGumDrawArray(GU_TRIANGLES, GU_INDEX_16BIT | GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 6, indices, square_indexed); 106 | 107 | endFrame(); 108 | 109 | camera.rot += 1.0f; 110 | camera.y = sinf(camera.rot / 180.0f) / 2.0f; 111 | } 112 | 113 | cleanup: 114 | 115 | // Terminate Graphics 116 | termGraphics(); 117 | 118 | // Exit Game 119 | sceKernelExitGame(); 120 | return 0; 121 | } -------------------------------------------------------------------------------- /4-Camera/sceGu/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/4-Camera/sceGu/circle.png -------------------------------------------------------------------------------- /4-Camera/sceGu/container.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/4-Camera/sceGu/container.jpg -------------------------------------------------------------------------------- /5-Sprites/gl/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = sprites 2 | OBJS = sprites.o ../../common/callbacks.o ../../common/common-gl.o 3 | 4 | INCDIR = ../../gu2gl/ 5 | CFLAGS = -Wall -std=c11 6 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 7 | ASFLAGS = $(CFLAGS) 8 | 9 | LIBDIR = 10 | LDFLAGS = 11 | LIBS= -lpspgum -lpspgu -lm 12 | 13 | EXTRA_TARGETS = EBOOT.PBP 14 | PSP_EBOOT_TITLE = Sprite Sample 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build.mak -------------------------------------------------------------------------------- /5-Sprites/gl/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/5-Sprites/gl/circle.png -------------------------------------------------------------------------------- /5-Sprites/gl/container.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/5-Sprites/gl/container.jpg -------------------------------------------------------------------------------- /5-Sprites/gl/sprites.c: -------------------------------------------------------------------------------- 1 | #include "../../common/callbacks.h" 2 | #include "../../common/common-gl.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // PSP Module Info 9 | PSP_MODULE_INFO("Sprite Sample", 0, 1, 1); 10 | PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU); 11 | 12 | // Global variables 13 | int running = 1; 14 | static unsigned int __attribute__((aligned(16))) list[262144]; 15 | 16 | typedef struct { 17 | void* data; 18 | u16* indices; 19 | u32 index_count; 20 | } Mesh; 21 | 22 | Mesh* create_mesh(u32 vcount, u32 index_count) { 23 | Mesh* mesh = malloc(sizeof(Mesh)); 24 | if(mesh == NULL) 25 | return NULL; 26 | 27 | mesh->data = memalign(16, sizeof(Vertex) * vcount); 28 | if(mesh->data == NULL) { 29 | free(mesh); 30 | return NULL; 31 | } 32 | mesh->indices = memalign(16, sizeof(u16) * index_count); 33 | if(mesh->indices == NULL) { 34 | free(mesh->data); 35 | free(mesh); 36 | return NULL; 37 | } 38 | 39 | mesh->index_count = index_count; 40 | 41 | return mesh; 42 | } 43 | 44 | void draw_mesh(Mesh* mesh) { 45 | glDrawElements(GL_TRIANGLES, GL_INDEX_16BIT | GL_TEXTURE_32BITF | GL_COLOR_8888 | GL_VERTEX_32BITF | GL_TRANSFORM_3D, mesh->index_count, mesh->indices, mesh->data); 46 | } 47 | 48 | void destroy_mesh(Mesh* mesh) { 49 | free(mesh->data); 50 | free(mesh->indices); 51 | free(mesh); 52 | } 53 | 54 | typedef struct { 55 | float x, y; 56 | float rot; 57 | float sx, sy; 58 | 59 | int layer; 60 | 61 | Mesh* mesh; 62 | Texture* tex; 63 | } Sprite; 64 | 65 | Vertex create_vert(float u, float v, unsigned int color, float x, float y, float z) { 66 | Vertex vert = { 67 | .u = u, 68 | .v = v, 69 | .color = color, 70 | .x = x, 71 | .y = y, 72 | .z = z 73 | }; 74 | 75 | return vert; 76 | } 77 | 78 | Sprite* create_sprite(float x, float y, float sx, float sy, Texture* tex) { 79 | Sprite* sprite = malloc(sizeof(Sprite)); 80 | if(sprite == NULL) 81 | return NULL; 82 | 83 | sprite->mesh = create_mesh(4, 6); 84 | if(sprite->mesh == NULL){ 85 | free(sprite); 86 | return NULL; 87 | } 88 | 89 | sprite->x = x; 90 | sprite->y = y; 91 | sprite->sx = sx; 92 | sprite->sy = sy; 93 | sprite->mesh->index_count = 6; 94 | sprite->tex = tex; 95 | sprite->layer = 0; 96 | sprite->rot = 0; 97 | 98 | 99 | ((Vertex*)sprite->mesh->data)[0] = create_vert(0, 0, 0xFFFFFFFF, -0.25f, -0.25f, 0.0f); 100 | ((Vertex*)sprite->mesh->data)[1] = create_vert(0, 1, 0xFFFFFFFF, -0.25f, 0.25f, 0.0f); 101 | ((Vertex*)sprite->mesh->data)[2] = create_vert(1, 1, 0xFFFFFFFF, 0.25f, 0.25f, 0.0f); 102 | ((Vertex*)sprite->mesh->data)[3] = create_vert(1, 0, 0xFFFFFFFF, 0.25f, -0.25f, 0.0f); 103 | 104 | sprite->mesh->indices[0] = 0; 105 | sprite->mesh->indices[1] = 1; 106 | sprite->mesh->indices[2] = 2; 107 | sprite->mesh->indices[3] = 2; 108 | sprite->mesh->indices[4] = 3; 109 | sprite->mesh->indices[5] = 0; 110 | 111 | sceKernelDcacheWritebackInvalidateAll(); 112 | 113 | return sprite; 114 | } 115 | 116 | void draw_sprite(Sprite* sprite) { 117 | glMatrixMode(GL_MODEL); 118 | glLoadIdentity(); 119 | 120 | ScePspFVector3 v = { 121 | .x = sprite->x, 122 | .y = sprite->y, 123 | .z = sprite->layer, 124 | }; 125 | 126 | gluTranslate(&v); 127 | gluRotateZ(sprite->rot); 128 | 129 | ScePspFVector3 s = { 130 | .x = sprite->sx, 131 | .y = sprite->sy, 132 | .z = 1.0f 133 | }; 134 | gluScale(&s); 135 | 136 | bind_texture(sprite->tex); 137 | draw_mesh(sprite->mesh); 138 | } 139 | 140 | void destroy_sprite(Sprite* sprite) { 141 | destroy_mesh(sprite->mesh); 142 | free(sprite); 143 | } 144 | 145 | typedef struct{ 146 | float x, y; 147 | float rot; 148 | } Camera2D; 149 | 150 | void apply_camera(const Camera2D* cam){ 151 | glMatrixMode(GL_VIEW); 152 | glLoadIdentity(); 153 | 154 | ScePspFVector3 v = {cam->x, cam->y, 0}; 155 | gluTranslate(&v); 156 | gluRotateZ(cam->rot / 180.0f * 3.14159f); 157 | 158 | glMatrixMode(GL_MODEL); 159 | glLoadIdentity(); 160 | } 161 | 162 | int main() { 163 | // Boilerplate 164 | SetupCallbacks(); 165 | 166 | // Initialize Graphics 167 | guglInit(list); 168 | 169 | // Initialize Matrices 170 | glMatrixMode(GL_PROJECTION); 171 | glLoadIdentity(); 172 | glOrtho(-16.0f / 9.0f, 16.0f / 9.0f, -1.0f, 1.0f, -10.0f, 10.0f); 173 | 174 | glMatrixMode(GL_VIEW); 175 | glLoadIdentity(); 176 | 177 | glMatrixMode(GL_MODEL); 178 | glLoadIdentity(); 179 | 180 | Texture* texture = load_texture("container.jpg", GL_TRUE, GL_TRUE); 181 | if(!texture) 182 | goto cleanup; 183 | 184 | Sprite* sprite = create_sprite(-0.5f, 0.0f, 1.0f, 1.0f, texture); 185 | if(!sprite) 186 | goto cleanup; 187 | 188 | Camera2D camera = { 189 | .x = 0, 190 | .y = 0, 191 | .rot = 45.0f 192 | }; 193 | 194 | //Main program loop 195 | while(running){ 196 | guglStartFrame(list, GL_FALSE); 197 | 198 | // We're doing a 2D, Textured render 199 | glDisable(GL_DEPTH_TEST); 200 | 201 | // Blending 202 | glBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); 203 | glEnable(GL_BLEND); 204 | 205 | //Clear background to Bjack 206 | glClearColor(0xFF000000); 207 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 208 | 209 | apply_camera(&camera); 210 | 211 | draw_sprite(sprite); 212 | 213 | guglSwapBuffers(GL_TRUE, GL_FALSE); 214 | 215 | camera.rot += 1.0f; 216 | camera.y = sinf(camera.rot / 180.0f) / 2.0f; 217 | } 218 | 219 | destroy_sprite(sprite); 220 | 221 | cleanup: 222 | 223 | // Terminate Graphics 224 | guglTerm(); 225 | 226 | // Exit Game 227 | sceKernelExitGame(); 228 | return 0; 229 | } -------------------------------------------------------------------------------- /5-Sprites/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/5-Sprites/img.png -------------------------------------------------------------------------------- /5-Sprites/sceGu/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = sprites 2 | OBJS = sprites.o ../../common/callbacks.o ../../common/common-sce.o 3 | 4 | INCDIR = ../../gu2gl/ 5 | CFLAGS = -Wall -std=c11 6 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 7 | ASFLAGS = $(CFLAGS) 8 | 9 | LIBDIR = 10 | LDFLAGS = 11 | LIBS= -lpspgum -lpspgu -lm 12 | 13 | EXTRA_TARGETS = EBOOT.PBP 14 | PSP_EBOOT_TITLE = Sprite Sample 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build.mak -------------------------------------------------------------------------------- /5-Sprites/sceGu/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/5-Sprites/sceGu/circle.png -------------------------------------------------------------------------------- /5-Sprites/sceGu/container.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/5-Sprites/sceGu/container.jpg -------------------------------------------------------------------------------- /5-Sprites/sceGu/sprites.c: -------------------------------------------------------------------------------- 1 | #include "../../common/callbacks.h" 2 | #include "../../common/common-sce.h" 3 | #include 4 | 5 | // Include Graphics Libraries 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // PSP Module Info 13 | PSP_MODULE_INFO("Sprite Sample", 0, 1, 1); 14 | PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU); 15 | 16 | // sceGuobal variables 17 | int running = 1; 18 | static unsigned int __attribute__((aligned(16))) list[262144]; 19 | 20 | typedef struct { 21 | void* data; 22 | u16* indices; 23 | u32 index_count; 24 | } Mesh; 25 | 26 | Mesh* create_mesh(u32 vcount, u32 index_count) { 27 | Mesh* mesh = malloc(sizeof(Mesh)); 28 | if(mesh == NULL) 29 | return NULL; 30 | 31 | mesh->data = memalign(16, sizeof(Vertex) * vcount); 32 | if(mesh->data == NULL) { 33 | free(mesh); 34 | return NULL; 35 | } 36 | mesh->indices = memalign(16, sizeof(u16) * index_count); 37 | if(mesh->indices == NULL) { 38 | free(mesh->data); 39 | free(mesh); 40 | return NULL; 41 | } 42 | 43 | mesh->index_count = index_count; 44 | 45 | return mesh; 46 | } 47 | 48 | void draw_mesh(Mesh* mesh) { 49 | sceGumDrawArray(GU_TRIANGLES, GU_INDEX_16BIT | GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, mesh->index_count, mesh->indices, mesh->data); 50 | } 51 | 52 | void destroy_mesh(Mesh* mesh) { 53 | free(mesh->data); 54 | free(mesh->indices); 55 | free(mesh); 56 | } 57 | 58 | typedef struct { 59 | float x, y; 60 | float rot; 61 | float sx, sy; 62 | 63 | int layer; 64 | 65 | Mesh* mesh; 66 | Texture* tex; 67 | } Sprite; 68 | 69 | Vertex create_vert(float u, float v, unsigned int color, float x, float y, float z) { 70 | Vertex vert = { 71 | .u = u, 72 | .v = v, 73 | .color = color, 74 | .x = x, 75 | .y = y, 76 | .z = z 77 | }; 78 | 79 | return vert; 80 | } 81 | 82 | Sprite* create_sprite(float x, float y, float sx, float sy, Texture* tex) { 83 | Sprite* sprite = malloc(sizeof(Sprite)); 84 | if(sprite == NULL) 85 | return NULL; 86 | 87 | sprite->mesh = create_mesh(4, 6); 88 | sprite->layer = 0; 89 | 90 | if(sprite->mesh == NULL){ 91 | free(sprite); 92 | return NULL; 93 | } 94 | 95 | ((Vertex*)sprite->mesh->data)[0] = create_vert(0, 0, 0xFFFFFFFF, -0.25f, -0.25f, 0.0f); 96 | ((Vertex*)sprite->mesh->data)[1] = create_vert(0, 1, 0xFFFFFFFF, -0.25f, 0.25f, 0.0f); 97 | ((Vertex*)sprite->mesh->data)[2] = create_vert(1, 1, 0xFFFFFFFF, 0.25f, 0.25f, 0.0f); 98 | ((Vertex*)sprite->mesh->data)[3] = create_vert(1, 0, 0xFFFFFFFF, 0.25f, -0.25f, 0.0f); 99 | 100 | sprite->mesh->indices[0] = 0; 101 | sprite->mesh->indices[1] = 1; 102 | sprite->mesh->indices[2] = 2; 103 | sprite->mesh->indices[3] = 2; 104 | sprite->mesh->indices[4] = 3; 105 | sprite->mesh->indices[5] = 0; 106 | 107 | sprite->mesh->index_count = 6; 108 | sprite->tex = tex; 109 | 110 | sprite->x = x; 111 | sprite->y = y; 112 | sprite->sx = sx; 113 | sprite->sy = sy; 114 | 115 | sceKernelDcacheWritebackInvalidateAll(); 116 | 117 | return sprite; 118 | } 119 | 120 | void draw_sprite(Sprite* sprite) { 121 | sceGumMatrixMode(GU_MODEL); 122 | sceGumLoadIdentity(); 123 | 124 | ScePspFVector3 v = { 125 | .x = sprite->x, 126 | .y = sprite->y, 127 | .z = sprite->layer, 128 | }; 129 | 130 | sceGumTranslate(&v); 131 | sceGumRotateZ(sprite->rot); 132 | 133 | ScePspFVector3 s = { 134 | .x = sprite->sx, 135 | .y = sprite->sy, 136 | .z = 1.0f 137 | }; 138 | sceGumScale(&s); 139 | 140 | bind_texture(sprite->tex); 141 | draw_mesh(sprite->mesh); 142 | } 143 | 144 | void destroy_sprite(Sprite* sprite) { 145 | destroy_mesh(sprite->mesh); 146 | free(sprite); 147 | } 148 | 149 | typedef struct{ 150 | float x, y; 151 | float rot; 152 | } Camera2D; 153 | 154 | void apply_camera(const Camera2D* cam){ 155 | sceGumMatrixMode(GU_VIEW); 156 | sceGumLoadIdentity(); 157 | 158 | ScePspFVector3 v = {cam->x, cam->y, 0}; 159 | sceGumTranslate(&v); 160 | sceGumRotateZ(cam->rot / 180.0f * 3.14159f); 161 | 162 | sceGumMatrixMode(GU_MODEL); 163 | sceGumLoadIdentity(); 164 | } 165 | 166 | int main() { 167 | // Boilerplate 168 | SetupCallbacks(); 169 | 170 | // Initialize Graphics 171 | initGraphics(list); 172 | 173 | // Initialize Matrices 174 | sceGumMatrixMode(GU_PROJECTION); 175 | sceGumLoadIdentity(); 176 | sceGumOrtho(-16.0f / 9.0f, 16.0f / 9.0f, -1.0f, 1.0f, -10.0f, 10.0f); 177 | 178 | sceGumMatrixMode(GU_VIEW); 179 | sceGumLoadIdentity(); 180 | 181 | sceGumMatrixMode(GU_MODEL); 182 | sceGumLoadIdentity(); 183 | 184 | Texture* texture = load_texture("container.jpg", GU_TRUE, GU_TRUE); 185 | if(!texture) 186 | goto cleanup; 187 | 188 | Sprite* sprite = create_sprite(-0.5f, 0.0f, 1.0f, 1.0f, texture); 189 | if(!sprite) 190 | goto cleanup; 191 | 192 | Camera2D camera = { 193 | .x = 0, 194 | .y = 0, 195 | .rot = 45.0f 196 | }; 197 | 198 | //Main program loop 199 | while(running){ 200 | startFrame(list); 201 | 202 | // We're doing a 2D, Textured render 203 | sceGuDisable(GU_DEPTH_TEST); 204 | 205 | // Blending 206 | sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); 207 | sceGuEnable(GU_BLEND); 208 | 209 | //Clear background to Bjack 210 | sceGuClearColor(0xFF000000); 211 | sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT | GU_STENCIL_BUFFER_BIT); 212 | 213 | apply_camera(&camera); 214 | 215 | draw_sprite(sprite); 216 | 217 | endFrame(); 218 | 219 | camera.rot += 1.0f; 220 | camera.y = sinf(camera.rot / 180.0f) / 2.0f; 221 | } 222 | 223 | cleanup: 224 | 225 | // Terminate Graphics 226 | termGraphics(); 227 | 228 | // Exit Game 229 | sceKernelExitGame(); 230 | return 0; 231 | } -------------------------------------------------------------------------------- /6-Tilemaps/gl/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = tilemaps 2 | OBJS = tilemaps.o ../../common/callbacks.o ../../common/common-gl.o 3 | 4 | INCDIR = ../../gu2gl/ 5 | CFLAGS = -Wall -std=c11 6 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 7 | ASFLAGS = $(CFLAGS) 8 | 9 | LIBDIR = 10 | LDFLAGS = 11 | LIBS= -lpspgum -lpspgu -lm 12 | 13 | EXTRA_TARGETS = EBOOT.PBP 14 | PSP_EBOOT_TITLE = Tilemap Sample 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build.mak -------------------------------------------------------------------------------- /6-Tilemaps/gl/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/6-Tilemaps/gl/default.png -------------------------------------------------------------------------------- /6-Tilemaps/gl/terrain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/6-Tilemaps/gl/terrain.png -------------------------------------------------------------------------------- /6-Tilemaps/gl/tilemaps.c: -------------------------------------------------------------------------------- 1 | #include "../../common/callbacks.h" 2 | #include "../../common/common-gl.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // PSP Module Info 9 | PSP_MODULE_INFO("Tilemap Sample", 0, 1, 1); 10 | PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU); 11 | 12 | // Global variables 13 | int running = 1; 14 | static unsigned int __attribute__((aligned(16))) list[262144]; 15 | 16 | typedef struct { 17 | void* data; 18 | u16* indices; 19 | u32 index_count; 20 | } Mesh; 21 | 22 | Mesh* create_mesh(u32 vcount, u32 index_count) { 23 | Mesh* mesh = malloc(sizeof(Mesh)); 24 | if(mesh == NULL) 25 | return NULL; 26 | 27 | mesh->data = memalign(16, sizeof(Vertex) * vcount); 28 | if(mesh->data == NULL) { 29 | free(mesh); 30 | return NULL; 31 | } 32 | mesh->indices = memalign(16, sizeof(u16) * index_count); 33 | if(mesh->indices == NULL) { 34 | free(mesh->data); 35 | free(mesh); 36 | return NULL; 37 | } 38 | 39 | mesh->index_count = index_count; 40 | 41 | return mesh; 42 | } 43 | 44 | void draw_mesh(Mesh* mesh) { 45 | glDrawElements(GL_TRIANGLES, GL_INDEX_16BIT | GL_TEXTURE_32BITF | GL_COLOR_8888 | GL_VERTEX_32BITF | GL_TRANSFORM_3D, mesh->index_count, mesh->indices, mesh->data); 46 | } 47 | 48 | void destroy_mesh(Mesh* mesh) { 49 | free(mesh->data); 50 | free(mesh->indices); 51 | free(mesh); 52 | } 53 | 54 | Vertex create_vert(float u, float v, unsigned int color, float x, float y, float z) { 55 | Vertex vert = { 56 | .u = u, 57 | .v = v, 58 | .color = color, 59 | .x = x, 60 | .y = y, 61 | .z = z 62 | }; 63 | 64 | return vert; 65 | } 66 | 67 | typedef struct { 68 | float w, h; 69 | } TextureAtlas; 70 | 71 | void get_uv_index(TextureAtlas* atlas, float* buf, int idx) { 72 | int row = idx / (int)atlas->w; 73 | int column = idx % (int)atlas->h; 74 | 75 | float sizeX = 1.f / ((float)atlas->w); 76 | float sizeY = 1.f / ((float)atlas->h); 77 | 78 | float y = (float)row * sizeY; 79 | float x = (float)column * sizeX; 80 | float h = y + sizeY; 81 | float w = x + sizeX; 82 | 83 | // 0 0 84 | // 0 1 85 | // 1 1 86 | // 1 0 87 | buf[0] = x; 88 | buf[1] = h; 89 | 90 | buf[2] = x; 91 | buf[3] = y; 92 | 93 | buf[4] = w; 94 | buf[5] = y; 95 | 96 | buf[6] = w; 97 | buf[7] = h; 98 | } 99 | 100 | typedef struct { 101 | int x, y; 102 | int tex_idx; 103 | } Tile; 104 | 105 | typedef struct { 106 | float x, y; 107 | float scale_x, scale_y; 108 | int w, h; 109 | TextureAtlas atlas; 110 | Texture* texture; 111 | Tile* tiles; 112 | Mesh* mesh; 113 | } Tilemap; 114 | 115 | Tilemap* create_tilemap(TextureAtlas atlas, Texture* texture, int sizex, int sizey) { 116 | Tilemap* tilemap = (Tilemap*)malloc(sizeof(Tilemap)); 117 | if(tilemap == NULL) 118 | return NULL; 119 | 120 | tilemap->tiles = (Tile*)malloc(sizeof(Tile) * sizex * sizey); 121 | if(tilemap->tiles == NULL){ 122 | free(tilemap); 123 | return NULL; 124 | } 125 | 126 | tilemap->mesh = create_mesh(sizex * sizey * 4, sizex * sizey * 6); 127 | if(tilemap->mesh == NULL){ 128 | free(tilemap->tiles); 129 | free(tilemap); 130 | } 131 | 132 | memset(tilemap->mesh->data, 0, sizeof(Vertex) * sizex * sizey); 133 | memset(tilemap->mesh->indices, 0, sizeof(u16) * sizex * sizey); 134 | memset(tilemap->tiles, 0, sizeof(Tile) * sizex * sizey); 135 | 136 | tilemap->atlas = atlas; 137 | tilemap->texture = texture; 138 | tilemap->x = 0; 139 | tilemap->y = 0; 140 | tilemap->w = sizex; 141 | tilemap->h = sizey; 142 | tilemap->mesh->index_count = tilemap->w * tilemap->h * 6; 143 | tilemap->scale_x = 16.0f; 144 | tilemap->scale_y = 16.0f; 145 | 146 | return tilemap; 147 | } 148 | 149 | void build_tilemap(Tilemap* tilemap) { 150 | for(int i = 0; i < tilemap->w * tilemap->h; i++){ 151 | float buf[8]; 152 | get_uv_index(&tilemap->atlas, buf, tilemap->tiles[i].tex_idx); 153 | 154 | float tx = (float)tilemap->tiles[i].x; 155 | float ty = (float)tilemap->tiles[i].y; 156 | float tw = tx + 1.0f; 157 | float th = ty + 1.0f; 158 | 159 | ((Vertex*)tilemap->mesh->data)[i * 4 + 0] = create_vert(buf[0], buf[1], 0xFFFFFFFF, tx, ty, 0.0f); 160 | ((Vertex*)tilemap->mesh->data)[i * 4 + 1] = create_vert(buf[2], buf[3], 0xFFFFFFFF, tx, th, 0.0f); 161 | ((Vertex*)tilemap->mesh->data)[i * 4 + 2] = create_vert(buf[4], buf[5], 0xFFFFFFFF, tw, th, 0.0f); 162 | ((Vertex*)tilemap->mesh->data)[i * 4 + 3] = create_vert(buf[6], buf[7], 0xFFFFFFFF, tw, ty, 0.0f); 163 | 164 | tilemap->mesh->indices[i * 6 + 0] = (i * 4) + 0; 165 | tilemap->mesh->indices[i * 6 + 1] = (i * 4) + 1; 166 | tilemap->mesh->indices[i * 6 + 2] = (i * 4) + 2; 167 | tilemap->mesh->indices[i * 6 + 3] = (i * 4) + 2; 168 | tilemap->mesh->indices[i * 6 + 4] = (i * 4) + 3; 169 | tilemap->mesh->indices[i * 6 + 5] = (i * 4) + 0; 170 | } 171 | sceKernelDcacheWritebackInvalidateAll(); 172 | } 173 | 174 | void draw_tilemap(Tilemap* tilemap) { 175 | glMatrixMode(GL_MODEL); 176 | glLoadIdentity(); 177 | 178 | ScePspFVector3 v = { 179 | .x = tilemap->x, 180 | .y = tilemap->y, 181 | .z = 0.0f, 182 | }; 183 | 184 | gluTranslate(&v); 185 | 186 | ScePspFVector3 v1 = { 187 | .x = tilemap->scale_x, 188 | .y = tilemap->scale_y, 189 | .z = 0.0f, 190 | }; 191 | 192 | gluScale(&v1); 193 | 194 | bind_texture(tilemap->texture); 195 | draw_mesh(tilemap->mesh); 196 | } 197 | 198 | void destroy_tilemap(Tilemap* tilemap) { 199 | destroy_mesh(tilemap->mesh); 200 | free(tilemap->tiles); 201 | free(tilemap); 202 | } 203 | 204 | typedef struct{ 205 | float x, y; 206 | float rot; 207 | } Camera2D; 208 | 209 | void apply_camera(const Camera2D* cam){ 210 | glMatrixMode(GL_VIEW); 211 | glLoadIdentity(); 212 | 213 | ScePspFVector3 v = {cam->x, cam->y, 0}; 214 | gluTranslate(&v); 215 | gluRotateZ(cam->rot / 180.0f * 3.14159f); 216 | 217 | glMatrixMode(GL_MODEL); 218 | glLoadIdentity(); 219 | } 220 | 221 | void draw_text(Tilemap* t, const char* str){ 222 | int len = strlen(str); 223 | 224 | for(int i = 0; i < len; i++){ 225 | char c = str[i]; 226 | 227 | Tile tile = { 228 | .x = i % t->w, 229 | .y = i / t->w, 230 | .tex_idx = c 231 | }; 232 | 233 | t->tiles[i] = tile; 234 | } 235 | } 236 | 237 | int main() { 238 | // Boilerplate 239 | SetupCallbacks(); 240 | 241 | // Initialize Graphics 242 | guglInit(list); 243 | 244 | // Initialize Matrices 245 | glMatrixMode(GL_PROJECTION); 246 | glLoadIdentity(); 247 | glOrtho(0, 480, 0.0f, 272.0f, -10.0f, 10.0f); 248 | 249 | glMatrixMode(GL_VIEW); 250 | glLoadIdentity(); 251 | 252 | glMatrixMode(GL_MODEL); 253 | glLoadIdentity(); 254 | 255 | Texture* texture = load_texture("terrain.png", GL_FALSE, GL_TRUE); 256 | Texture* texture2 = load_texture("default.png", GL_FALSE, GL_TRUE); 257 | 258 | TextureAtlas atlas = {.w = 16, .h = 16}; 259 | Tilemap* tilemap = create_tilemap(atlas, texture, 8, 8); 260 | Tilemap* tilemap2 = create_tilemap(atlas, texture2, 16, 16); 261 | tilemap2->x = 144; 262 | tilemap2->y = 16; 263 | 264 | draw_text(tilemap2, "Hello World!"); 265 | build_tilemap(tilemap2); 266 | 267 | for(int y = 0; y < 8; y++) { 268 | for(int x = 0; x < 8; x++) { 269 | Tile tile = { 270 | .x = x, 271 | .y = y, 272 | .tex_idx = x + y * 8 273 | }; 274 | tilemap->tiles[x + y * 8] = tile; 275 | } 276 | } 277 | 278 | tilemap->x = 176; 279 | tilemap->y = 136; 280 | build_tilemap(tilemap); 281 | 282 | //Main program loop 283 | while(running){ 284 | guglStartFrame(list, GL_FALSE); 285 | 286 | // We're doing a 2D, Textured render 287 | glDisable(GL_DEPTH_TEST); 288 | 289 | // Blending 290 | glBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); 291 | glEnable(GL_BLEND); 292 | 293 | //Clear background to Bjack 294 | glClearColor(0xFF000000); 295 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 296 | 297 | draw_tilemap(tilemap); 298 | draw_tilemap(tilemap2); 299 | 300 | guglSwapBuffers(GL_TRUE, GL_FALSE); 301 | } 302 | 303 | destroy_tilemap(tilemap); 304 | destroy_tilemap(tilemap2); 305 | 306 | // Terminate Graphics 307 | guglTerm(); 308 | 309 | // Exit Game 310 | sceKernelExitGame(); 311 | return 0; 312 | } -------------------------------------------------------------------------------- /6-Tilemaps/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/6-Tilemaps/img.png -------------------------------------------------------------------------------- /6-Tilemaps/sceGu/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = tilemaps 2 | OBJS = tilemaps.o ../../common/callbacks.o ../../common/common-sce.o 3 | 4 | INCDIR = ../../gu2gl/ 5 | CFLAGS = -Wall -std=c11 6 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 7 | ASFLAGS = $(CFLAGS) 8 | 9 | LIBDIR = 10 | LDFLAGS = 11 | LIBS= -lpspgum -lpspgu -lm 12 | 13 | EXTRA_TARGETS = EBOOT.PBP 14 | PSP_EBOOT_TITLE = Tilemap Sample 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build.mak -------------------------------------------------------------------------------- /6-Tilemaps/sceGu/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/6-Tilemaps/sceGu/default.png -------------------------------------------------------------------------------- /6-Tilemaps/sceGu/terrain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IridescentRose/PSP-GPU-Tutorials/81217f25164839867f7dc5f49af29bbc0c517416/6-Tilemaps/sceGu/terrain.png -------------------------------------------------------------------------------- /6-Tilemaps/sceGu/tilemaps.c: -------------------------------------------------------------------------------- 1 | #include "../../common/callbacks.h" 2 | #include "../../common/common-sce.h" 3 | #include 4 | 5 | // Include Graphics Libraries 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // PSP Module Info 13 | PSP_MODULE_INFO("Tilemap Sample", 0, 1, 1); 14 | PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU); 15 | 16 | // sceGuobal variables 17 | int running = 1; 18 | static unsigned int __attribute__((aligned(16))) list[262144]; 19 | 20 | typedef struct { 21 | void* data; 22 | u16* indices; 23 | u32 index_count; 24 | } Mesh; 25 | 26 | Mesh* create_mesh(u32 vcount, u32 index_count) { 27 | Mesh* mesh = malloc(sizeof(Mesh)); 28 | if(mesh == NULL) 29 | return NULL; 30 | 31 | mesh->data = memalign(16, sizeof(Vertex) * vcount); 32 | if(mesh->data == NULL) { 33 | free(mesh); 34 | return NULL; 35 | } 36 | mesh->indices = memalign(16, sizeof(u16) * index_count); 37 | if(mesh->indices == NULL) { 38 | free(mesh->data); 39 | free(mesh); 40 | return NULL; 41 | } 42 | 43 | mesh->index_count = index_count; 44 | 45 | return mesh; 46 | } 47 | 48 | void draw_mesh(Mesh* mesh) { 49 | sceGumDrawArray(GU_TRIANGLES, GU_INDEX_16BIT | GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, mesh->index_count, mesh->indices, mesh->data); 50 | } 51 | 52 | void destroy_mesh(Mesh* mesh) { 53 | free(mesh->data); 54 | free(mesh->indices); 55 | free(mesh); 56 | } 57 | 58 | Vertex create_vert(float u, float v, unsigned int color, float x, float y, float z) { 59 | Vertex vert = { 60 | .u = u, 61 | .v = v, 62 | .color = color, 63 | .x = x, 64 | .y = y, 65 | .z = z 66 | }; 67 | 68 | return vert; 69 | } 70 | 71 | typedef struct { 72 | float w, h; 73 | } TextureAtlas; 74 | 75 | void get_uv_index(TextureAtlas* atlas, float* buf, int idx) { 76 | int row = idx / (int)atlas->w; 77 | int column = idx % (int)atlas->h; 78 | 79 | float sizeX = 1.f / ((float)atlas->w); 80 | float sizeY = 1.f / ((float)atlas->h); 81 | 82 | float y = (float)row * sizeY; 83 | float x = (float)column * sizeX; 84 | float h = y + sizeY; 85 | float w = x + sizeX; 86 | 87 | // 0 0 88 | // 0 1 89 | // 1 1 90 | // 1 0 91 | buf[0] = x; 92 | buf[1] = h; 93 | 94 | buf[2] = x; 95 | buf[3] = y; 96 | 97 | buf[4] = w; 98 | buf[5] = y; 99 | 100 | buf[6] = w; 101 | buf[7] = h; 102 | } 103 | 104 | typedef struct { 105 | int x, y; 106 | int tex_idx; 107 | } Tile; 108 | 109 | typedef struct { 110 | float x, y; 111 | float scale_x, scale_y; 112 | int w, h; 113 | TextureAtlas atlas; 114 | Texture* texture; 115 | Tile* tiles; 116 | Mesh* mesh; 117 | } Tilemap; 118 | 119 | Tilemap* create_tilemap(TextureAtlas atlas, Texture* texture, int sizex, int sizey) { 120 | Tilemap* tilemap = (Tilemap*)malloc(sizeof(Tilemap)); 121 | if(tilemap == NULL) 122 | return NULL; 123 | 124 | tilemap->tiles = (Tile*)malloc(sizeof(Tile) * sizex * sizey); 125 | if(tilemap->tiles == NULL){ 126 | free(tilemap); 127 | return NULL; 128 | } 129 | 130 | tilemap->mesh = create_mesh(sizex * sizey * 4, sizex * sizey * 6); 131 | if(tilemap->mesh == NULL){ 132 | free(tilemap->tiles); 133 | free(tilemap); 134 | } 135 | 136 | memset(tilemap->mesh->data, 0, sizeof(Vertex) * sizex * sizey); 137 | memset(tilemap->mesh->indices, 0, sizeof(u16) * sizex * sizey); 138 | memset(tilemap->tiles, 0, sizeof(Tile) * sizex * sizey); 139 | 140 | tilemap->atlas = atlas; 141 | tilemap->texture = texture; 142 | tilemap->x = 0; 143 | tilemap->y = 0; 144 | tilemap->w = sizex; 145 | tilemap->h = sizey; 146 | tilemap->mesh->index_count = tilemap->w * tilemap->h * 6; 147 | tilemap->scale_x = 16.0f; 148 | tilemap->scale_y = 16.0f; 149 | 150 | return tilemap; 151 | } 152 | 153 | void build_tilemap(Tilemap* tilemap) { 154 | for(int i = 0; i < tilemap->w * tilemap->h; i++){ 155 | float buf[8]; 156 | get_uv_index(&tilemap->atlas, buf, tilemap->tiles[i].tex_idx); 157 | 158 | float tx = (float)tilemap->tiles[i].x; 159 | float ty = (float)tilemap->tiles[i].y; 160 | float tw = tx + 1.0f; 161 | float th = ty + 1.0f; 162 | 163 | ((Vertex*)tilemap->mesh->data)[i * 4 + 0] = create_vert(buf[0], buf[1], 0xFFFFFFFF, tx, ty, 0.0f); 164 | ((Vertex*)tilemap->mesh->data)[i * 4 + 1] = create_vert(buf[2], buf[3], 0xFFFFFFFF, tx, th, 0.0f); 165 | ((Vertex*)tilemap->mesh->data)[i * 4 + 2] = create_vert(buf[4], buf[5], 0xFFFFFFFF, tw, th, 0.0f); 166 | ((Vertex*)tilemap->mesh->data)[i * 4 + 3] = create_vert(buf[6], buf[7], 0xFFFFFFFF, tw, ty, 0.0f); 167 | 168 | tilemap->mesh->indices[i * 6 + 0] = (i * 4) + 0; 169 | tilemap->mesh->indices[i * 6 + 1] = (i * 4) + 1; 170 | tilemap->mesh->indices[i * 6 + 2] = (i * 4) + 2; 171 | tilemap->mesh->indices[i * 6 + 3] = (i * 4) + 2; 172 | tilemap->mesh->indices[i * 6 + 4] = (i * 4) + 3; 173 | tilemap->mesh->indices[i * 6 + 5] = (i * 4) + 0; 174 | } 175 | sceKernelDcacheWritebackInvalidateAll(); 176 | } 177 | 178 | void draw_tilemap(Tilemap* tilemap) { 179 | sceGumMatrixMode(GU_MODEL); 180 | sceGumLoadIdentity(); 181 | 182 | ScePspFVector3 v = { 183 | .x = tilemap->x, 184 | .y = tilemap->y, 185 | .z = 0.0f, 186 | }; 187 | 188 | sceGumTranslate(&v); 189 | 190 | ScePspFVector3 v1 = { 191 | .x = tilemap->scale_x, 192 | .y = tilemap->scale_y, 193 | .z = 0.0f, 194 | }; 195 | 196 | sceGumScale(&v1); 197 | 198 | bind_texture(tilemap->texture); 199 | draw_mesh(tilemap->mesh); 200 | } 201 | 202 | void destroy_tilemap(Tilemap* tilemap) { 203 | destroy_mesh(tilemap->mesh); 204 | free(tilemap->tiles); 205 | free(tilemap); 206 | } 207 | 208 | 209 | 210 | typedef struct{ 211 | float x, y; 212 | float rot; 213 | } Camera2D; 214 | 215 | void apply_camera(const Camera2D* cam){ 216 | sceGumMatrixMode(GU_VIEW); 217 | sceGumLoadIdentity(); 218 | 219 | ScePspFVector3 v = {cam->x, cam->y, 0}; 220 | sceGumTranslate(&v); 221 | sceGumRotateZ(cam->rot / 180.0f * 3.14159f); 222 | 223 | sceGumMatrixMode(GU_MODEL); 224 | sceGumLoadIdentity(); 225 | } 226 | 227 | void draw_text(Tilemap* t, const char* str){ 228 | int len = strlen(str); 229 | 230 | for(int i = 0; i < len; i++){ 231 | char c = str[i]; 232 | 233 | Tile tile = { 234 | .x = i % t->w, 235 | .y = i / t->w, 236 | .tex_idx = c 237 | }; 238 | 239 | t->tiles[i] = tile; 240 | } 241 | } 242 | 243 | int main() { 244 | // Boilerplate 245 | SetupCallbacks(); 246 | 247 | // Initialize Graphics 248 | initGraphics(list); 249 | 250 | // Initialize Matrices 251 | sceGumMatrixMode(GU_PROJECTION); 252 | sceGumLoadIdentity(); 253 | sceGumOrtho(0, 480, 0.0f, 272.0f, -10.0f, 10.0f); 254 | 255 | sceGumMatrixMode(GU_VIEW); 256 | sceGumLoadIdentity(); 257 | 258 | sceGumMatrixMode(GU_MODEL); 259 | sceGumLoadIdentity(); 260 | 261 | Texture* texture = load_texture("terrain.png", GU_FALSE, GU_TRUE); 262 | Texture* texture2 = load_texture("default.png", GU_FALSE, GU_TRUE); 263 | 264 | TextureAtlas atlas = {.w = 16, .h = 16}; 265 | Tilemap* tilemap = create_tilemap(atlas, texture, 8, 8); 266 | Tilemap* tilemap2 = create_tilemap(atlas, texture2, 16, 16); 267 | tilemap2->x = 144; 268 | tilemap2->y = 16; 269 | 270 | draw_text(tilemap2, "Hello World!"); 271 | build_tilemap(tilemap2); 272 | 273 | for(int y = 0; y < 8; y++) { 274 | for(int x = 0; x < 8; x++) { 275 | Tile tile = { 276 | .x = x, 277 | .y = y, 278 | .tex_idx = x + y * 8 279 | }; 280 | tilemap->tiles[x + y * 8] = tile; 281 | } 282 | } 283 | 284 | tilemap->x = 176; 285 | tilemap->y = 136; 286 | build_tilemap(tilemap); 287 | 288 | //Main program loop 289 | while(running){ 290 | startFrame(list); 291 | 292 | // We're doing a 2D, Textured render 293 | sceGuDisable(GU_DEPTH_TEST); 294 | 295 | // Blending 296 | sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); 297 | sceGuEnable(GU_BLEND); 298 | 299 | //Clear background to Bjack 300 | sceGuClearColor(0xFF000000); 301 | sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT | GU_STENCIL_BUFFER_BIT); 302 | 303 | draw_tilemap(tilemap); 304 | draw_tilemap(tilemap2); 305 | 306 | 307 | endFrame(); 308 | } 309 | destroy_tilemap(tilemap); 310 | destroy_tilemap(tilemap2); 311 | 312 | // Terminate Graphics 313 | termGraphics(); 314 | 315 | // Exit Game 316 | sceKernelExitGame(); 317 | return 0; 318 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Nathan Bourgeois 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PSP-GPU-Tutorials 2 | The PSP Lacks a lot of GPU tutorials. Let's fix that. Also hosted on psp-dev.org 3 | 4 | ## Tutorial 1 - Context 5 | - [Tutorial](https://psp-dev.org/doku.php?id=tutorial:context) 6 | - [Source](https://github.com/IridescentRose/PSP-GPU-Tutorials/tree/master/1-Context) 7 | 8 | ## Tutorial 2 - Drawing / Indices 9 | ![Drawing Result](2-Drawing/img.png) 10 | 11 | - [Tutorial](https://psp-dev.org/doku.php?id=tutorial:drawing) 12 | - [Source](https://github.com/IridescentRose/PSP-GPU-Tutorials/tree/master/2-Drawing) 13 | 14 | ## Tutorial 3 - Drawing / Indices 15 | ![Drawing Result](3-Textures/img.png) 16 | 17 | - [Tutorial](https://psp-dev.org/doku.php?id=tutorial:texture) 18 | - [Source](https://github.com/IridescentRose/PSP-GPU-Tutorials/tree/master/3-Textures) 19 | 20 | ## Tutorial 4 - Camera & Matrices 21 | ![Drawing Result](4-Camera/img.png) 22 | 23 | - [Tutorial](https://psp-dev.org/doku.php?id=tutorial:camera) 24 | - [Source](https://github.com/IridescentRose/PSP-GPU-Tutorials/tree/master/4-Camera) 25 | 26 | ## Tutorial 5 - Mesh & Sprites 27 | ![Drawing Result](5-Sprites/img.png) 28 | 29 | - [Tutorial](https://psp-dev.org/doku.php?id=tutorial:sprites) 30 | - [Source](https://github.com/IridescentRose/PSP-GPU-Tutorials/tree/master/5-Sprites) 31 | 32 | ## Tutorial 6- Tilemaps 33 | 34 | ![Drawing Result](6-Tilemaps/img.png) 35 | - [Tutorial](https://psp-dev.org/doku.php?id=tutorial:tilemap) 36 | - [Source](https://github.com/IridescentRose/PSP-GPU-Tutorials/tree/master/6-Tilemaps) -------------------------------------------------------------------------------- /common/callbacks.c: -------------------------------------------------------------------------------- 1 | #include "callbacks.h" 2 | 3 | int exit_callback(int arg1, int arg2, void* common){ 4 | sceKernelExitGame(); 5 | return 0; 6 | } 7 | 8 | int CallbackThread(SceSize args, void* argp) { 9 | int cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL); 10 | sceKernelRegisterExitCallback(cbid); 11 | sceKernelSleepThreadCB(); 12 | 13 | return 0; 14 | } 15 | 16 | int SetupCallbacks(void) { 17 | int thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0); 18 | if (thid >= 0) { 19 | sceKernelStartThread(thid, 0, 0); 20 | } 21 | return thid; 22 | } -------------------------------------------------------------------------------- /common/callbacks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | int SetupCallbacks(void); -------------------------------------------------------------------------------- /common/common-gl.c: -------------------------------------------------------------------------------- 1 | #define STB_IMAGE_IMPLEMENTATION 2 | #include "../../common/stb_image.h" 3 | 4 | #define GUGL_IMPLEMENTATION 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "common-gl.h" 10 | 11 | 12 | void swizzle_fast(u8 *out, const u8 *in, const unsigned int width, const unsigned int height) { 13 | unsigned int blockx, blocky; 14 | unsigned int j; 15 | 16 | unsigned int width_blocks = (width / 16); 17 | unsigned int height_blocks = (height / 8); 18 | 19 | unsigned int src_pitch = (width - 16) / 4; 20 | unsigned int src_row = width * 8; 21 | 22 | const u8 *ysrc = in; 23 | u32 *dst = (u32 *)out; 24 | 25 | for (blocky = 0; blocky < height_blocks; ++blocky) { 26 | const u8 *xsrc = ysrc; 27 | for (blockx = 0; blockx < width_blocks; ++blockx) { 28 | const u32 *src = (u32 *)xsrc; 29 | for (j = 0; j < 8; ++j) { 30 | *(dst++) = *(src++); 31 | *(dst++) = *(src++); 32 | *(dst++) = *(src++); 33 | *(dst++) = *(src++); 34 | src += src_pitch; 35 | } 36 | xsrc += 16; 37 | } 38 | ysrc += src_row; 39 | } 40 | } 41 | 42 | unsigned int pow2(const unsigned int value) { 43 | unsigned int poweroftwo = 1; 44 | while (poweroftwo < value) { 45 | poweroftwo <<= 1; 46 | } 47 | return poweroftwo; 48 | } 49 | 50 | void copy_texture_data(void* dest, const void* src, const int pW, const int width, const int height){ 51 | for (unsigned int y = 0; y < height; y++) { 52 | for (unsigned int x = 0; x < width; x++) { 53 | ((unsigned int*)dest)[x + y * pW] = ((unsigned int *)src)[x + y * width]; 54 | } 55 | } 56 | } 57 | 58 | Texture* load_texture(const char* filename, const int flip, const int vram) { 59 | int width, height, nrChannels; 60 | stbi_set_flip_vertically_on_load(flip); 61 | unsigned char *data = stbi_load(filename, &width, &height, 62 | &nrChannels, STBI_rgb_alpha); 63 | 64 | if(!data) 65 | return NULL; 66 | 67 | Texture* tex = (Texture*)malloc(sizeof(Texture)); 68 | tex->width = width; 69 | tex->height = height; 70 | tex->pW = pow2(width); 71 | tex->pH = pow2(height); 72 | 73 | unsigned int *dataBuffer = 74 | (unsigned int *)memalign(16, tex->pH * tex->pW * 4); 75 | 76 | // Copy to Data Buffer 77 | copy_texture_data(dataBuffer, data, tex->pW, tex->width, tex->height); 78 | 79 | // Free STB Data 80 | stbi_image_free(data); 81 | 82 | unsigned int* swizzled_pixels = NULL; 83 | size_t size = tex->pH * tex->pW * 4; 84 | if(vram){ 85 | swizzled_pixels = getStaticVramTexture(tex->pW, tex->pH, GU_PSM_8888); 86 | } else { 87 | swizzled_pixels = (unsigned int *)memalign(16, size); 88 | } 89 | 90 | swizzle_fast((u8*)swizzled_pixels, (const u8*)dataBuffer, tex->pW * 4, tex->pH); 91 | 92 | free(dataBuffer); 93 | tex->data = swizzled_pixels; 94 | 95 | sceKernelDcacheWritebackInvalidateAll(); 96 | 97 | return tex; 98 | } 99 | 100 | void bind_texture(Texture* tex) { 101 | if(tex == NULL) 102 | return; 103 | 104 | glTexMode(GU_PSM_8888, 0, 0, 1); 105 | glTexFunc(GL_TFX_MODULATE, GL_TCC_RGBA); 106 | glTexFilter(GL_NEAREST, GL_NEAREST); 107 | glTexWrap(GL_REPEAT, GL_REPEAT); 108 | glTexImage(0, tex->pW, tex->pH, tex->pW, tex->data); 109 | } 110 | 111 | void reset_transform(float x, float y, float z){ 112 | ScePspFVector3 v = {x, y, z}; 113 | glLoadIdentity(); 114 | gluTranslate(&v); 115 | } -------------------------------------------------------------------------------- /common/common-gl.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_GL_H_INCLUDED 2 | #define COMMON_GL_H_INCLUDED 3 | 4 | #if __cplusplus__ 5 | extern "C"{ 6 | #endif 7 | 8 | typedef struct 9 | { 10 | float u, v; 11 | unsigned int color; 12 | float x, y, z; 13 | } Vertex; 14 | 15 | typedef struct { 16 | unsigned int width, height; 17 | unsigned int pW, pH; 18 | void* data; 19 | }Texture; 20 | 21 | void reset_transform(float x, float y, float z); 22 | Texture* load_texture(const char* filename, const int flip, const int vram); 23 | void bind_texture(Texture* tex); 24 | 25 | #if __cplusplus__ 26 | }; 27 | #endif 28 | 29 | #endif -------------------------------------------------------------------------------- /common/common-sce.c: -------------------------------------------------------------------------------- 1 | #define STB_IMAGE_IMPLEMENTATION 2 | #include "../../common/stb_image.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "common-sce.h" 11 | 12 | void swizzle_fast(u8 *out, const u8 *in, const unsigned int width, const unsigned int height) { 13 | unsigned int blockx, blocky; 14 | unsigned int j; 15 | 16 | unsigned int width_blocks = (width / 16); 17 | unsigned int height_blocks = (height / 8); 18 | 19 | unsigned int src_pitch = (width - 16) / 4; 20 | unsigned int src_row = width * 8; 21 | 22 | const u8 *ysrc = in; 23 | u32 *dst = (u32 *)out; 24 | 25 | for (blocky = 0; blocky < height_blocks; ++blocky) { 26 | const u8 *xsrc = ysrc; 27 | for (blockx = 0; blockx < width_blocks; ++blockx) { 28 | const u32 *src = (u32 *)xsrc; 29 | for (j = 0; j < 8; ++j) { 30 | *(dst++) = *(src++); 31 | *(dst++) = *(src++); 32 | *(dst++) = *(src++); 33 | *(dst++) = *(src++); 34 | src += src_pitch; 35 | } 36 | xsrc += 16; 37 | } 38 | ysrc += src_row; 39 | } 40 | } 41 | 42 | unsigned int pow2(const unsigned int value) { 43 | unsigned int poweroftwo = 1; 44 | while (poweroftwo < value) { 45 | poweroftwo <<= 1; 46 | } 47 | return poweroftwo; 48 | } 49 | 50 | void copy_texture_data(void* dest, const void* src, const int pW, const int width, const int height){ 51 | for (unsigned int y = 0; y < height; y++) { 52 | for (unsigned int x = 0; x < width; x++) { 53 | ((unsigned int*)dest)[x + y * pW] = ((unsigned int *)src)[x + y * width]; 54 | } 55 | } 56 | } 57 | Texture* load_texture(const char* filename, const int flip, const int vram) { 58 | int width, height, nrChannels; 59 | stbi_set_flip_vertically_on_load(flip); 60 | unsigned char *data = stbi_load(filename, &width, &height, 61 | &nrChannels, STBI_rgb_alpha); 62 | 63 | if(!data) 64 | return NULL; 65 | 66 | Texture* tex = (Texture*)malloc(sizeof(Texture)); 67 | tex->width = width; 68 | tex->height = height; 69 | tex->pW = pow2(width); 70 | tex->pH = pow2(height); 71 | 72 | unsigned int *dataBuffer = 73 | (unsigned int *)memalign(16, tex->pH * tex->pW * 4); 74 | 75 | // Copy to Data Buffer 76 | copy_texture_data(dataBuffer, data, tex->pW, tex->width, tex->height); 77 | 78 | // Free STB Data 79 | stbi_image_free(data); 80 | 81 | unsigned int* swizzled_pixels = NULL; 82 | size_t size = tex->pH * tex->pW * 4; 83 | if(vram){ 84 | swizzled_pixels = getStaticVramTexture(tex->pW, tex->pH, GU_PSM_8888); 85 | } else { 86 | swizzled_pixels = (unsigned int *)memalign(16, size); 87 | } 88 | 89 | swizzle_fast((u8*)swizzled_pixels, (const u8*)dataBuffer, tex->pW * 4, tex->pH); 90 | 91 | free(dataBuffer); 92 | tex->data = swizzled_pixels; 93 | 94 | sceKernelDcacheWritebackInvalidateAll(); 95 | 96 | return tex; 97 | } 98 | 99 | void bind_texture(Texture* tex) { 100 | if(tex == NULL) 101 | return; 102 | 103 | sceGuTexMode(GU_PSM_8888, 0, 0, 1); 104 | sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA); 105 | sceGuTexFilter(GU_NEAREST, GU_NEAREST); 106 | sceGuTexWrap(GU_REPEAT, GU_REPEAT); 107 | sceGuTexImage(0, tex->pW, tex->pH, tex->pW, tex->data); 108 | } 109 | 110 | void reset_transform(float x, float y, float z){ 111 | ScePspFVector3 v = {x, y, z}; 112 | sceGumLoadIdentity(); 113 | sceGumTranslate(&v); 114 | } 115 | 116 | 117 | // Get Memory Size 118 | unsigned int getMemorySize(unsigned int width, unsigned int height, unsigned int psm) 119 | { 120 | switch (psm) 121 | { 122 | case GU_PSM_T4: 123 | return (width * height) >> 1; 124 | 125 | case GU_PSM_T8: 126 | return width * height; 127 | 128 | case GU_PSM_5650: 129 | case GU_PSM_5551: 130 | case GU_PSM_4444: 131 | case GU_PSM_T16: 132 | return 2 * width * height; 133 | 134 | case GU_PSM_8888: 135 | case GU_PSM_T32: 136 | return 4 * width * height; 137 | 138 | default: 139 | return 0; 140 | } 141 | } 142 | 143 | // Vram Buffer Request 144 | void* getStaticVramBuffer(unsigned int width, unsigned int height, unsigned int psm) 145 | { 146 | static unsigned int staticOffset = 0; 147 | unsigned int memSize = getMemorySize(width,height,psm); 148 | void* result = (void*)staticOffset; 149 | staticOffset += memSize; 150 | 151 | return result; 152 | } 153 | 154 | // Vram Texture Request 155 | void* getStaticVramTexture(unsigned int width, unsigned int height, unsigned int psm) 156 | { 157 | void* result = getStaticVramBuffer(width,height,psm); 158 | return (void*)(((unsigned int)result) + ((unsigned int)sceGeEdramGetAddr())); 159 | } 160 | 161 | 162 | // Initialize Graphics 163 | void initGraphics(void* list) { 164 | void* fbp0 = getStaticVramBuffer(PSP_BUF_WIDTH,PSP_SCR_HEIGHT,GU_PSM_8888); 165 | void* fbp1 = getStaticVramBuffer(PSP_BUF_WIDTH,PSP_SCR_HEIGHT,GU_PSM_8888); 166 | void* zbp = getStaticVramBuffer(PSP_BUF_WIDTH,PSP_SCR_HEIGHT,GU_PSM_4444); 167 | 168 | sceGuInit(); 169 | 170 | sceGuStart(GU_DIRECT,list); 171 | sceGuDrawBuffer(GU_PSM_8888,fbp0,PSP_BUF_WIDTH); 172 | sceGuDispBuffer(PSP_SCR_WIDTH,PSP_SCR_HEIGHT,fbp1,PSP_BUF_WIDTH); 173 | sceGuDepthBuffer(zbp,PSP_BUF_WIDTH); 174 | sceGuOffset(2048 - (PSP_SCR_WIDTH/2),2048 - (PSP_SCR_HEIGHT/2)); 175 | sceGuViewport(2048,2048,PSP_SCR_WIDTH,PSP_SCR_HEIGHT); 176 | sceGuDepthRange(65535,0); 177 | sceGuScissor(0,0,PSP_SCR_WIDTH,PSP_SCR_HEIGHT); 178 | sceGuEnable(GU_SCISSOR_TEST); 179 | sceGuDepthFunc(GU_GEQUAL); 180 | sceGuEnable(GU_DEPTH_TEST); 181 | sceGuFrontFace(GU_CW); 182 | sceGuShadeModel(GU_SMOOTH); 183 | sceGuEnable(GU_CULL_FACE); 184 | sceGuEnable(GU_TEXTURE_2D); 185 | sceGuEnable(GU_CLIP_PLANES); 186 | sceGuFinish(); 187 | sceGuSync(0,0); 188 | 189 | sceDisplayWaitVblankStart(); 190 | sceGuDisplay(GU_TRUE); 191 | } 192 | 193 | // Start Frame 194 | void startFrame(void* list) { 195 | sceGuStart(GU_DIRECT, list); 196 | } 197 | 198 | // End Frame 199 | void endFrame() { 200 | sceGuFinish(); 201 | sceGuSync(0, 0); 202 | sceDisplayWaitVblankStart(); 203 | sceGuSwapBuffers(); 204 | } 205 | 206 | // End Graphics 207 | void termGraphics() { 208 | sceGuTerm(); 209 | } 210 | -------------------------------------------------------------------------------- /common/common-sce.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_GL_H_INCLUDED 2 | #define COMMON_GL_H_INCLUDED 3 | 4 | #if __cplusplus__ 5 | extern "C"{ 6 | #endif 7 | 8 | // Define PSP Width / Height 9 | #define PSP_BUF_WIDTH (512) 10 | #define PSP_SCR_WIDTH (480) 11 | #define PSP_SCR_HEIGHT (272) 12 | 13 | typedef struct 14 | { 15 | float u, v; 16 | unsigned int color; 17 | float x, y, z; 18 | } Vertex; 19 | 20 | typedef struct { 21 | unsigned int width, height; 22 | unsigned int pW, pH; 23 | void* data; 24 | }Texture; 25 | 26 | void reset_transform(float x, float y, float z); 27 | Texture* load_texture(const char* filename, const int flip, const int vram); 28 | void bind_texture(Texture* tex); 29 | 30 | unsigned int getMemorySize(unsigned int width, unsigned int height, unsigned int psm); 31 | void* getStaticVramBuffer(unsigned int width, unsigned int height, unsigned int psm); 32 | void* getStaticVramTexture(unsigned int width, unsigned int height, unsigned int psm); 33 | 34 | void initGraphics(void* list); 35 | void startFrame(void* list); 36 | void endFrame(); 37 | void termGraphics(); 38 | 39 | 40 | #if __cplusplus__ 41 | }; 42 | #endif 43 | 44 | #endif --------------------------------------------------------------------------------