Difference between revisions of "PSP homebrew development"
(adding VFPU stuff) |
(+link to swizzle) |
||
(3 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | == | + | The PSP kernel is built up of multiple separate "Modules"; it is not a monolithic kernel in the usual sense. User applications are also considered modules, and modules can be loaded and started almost at will. They can be loaded to fixed locations or relocatable locations, and can export and import functions from other modules |
+ | |||
+ | The PSP kernel has no real concept of a "process" as you would find in other operating systems. | ||
+ | |||
+ | == Executable Formats == | ||
+ | The PSP uses the Executable and Linking Format (ELF) as the base for its modules, but can load the following types of files natively: | ||
+ | * ELF - Basic ELF format linked to a hardcoded address (typically 0x8900000) | ||
+ | * PRX - Customized ELF format, can be relocated anywhere in memory space | ||
+ | * ~PSP - An encrypted wrapper format for ELF or PRX | ||
+ | |||
+ | While the PSPSDK can produce ELF or PRX formats, it cannot produce the proprietary encrypted ~PSP format. | ||
+ | |||
+ | == Graphics == | ||
Note that while pixel depths are referred to by RGBA below, the actual bit order is BGRA (or BGR for formats without alpha). | Note that while pixel depths are referred to by RGBA below, the actual bit order is BGRA (or BGR for formats without alpha). | ||
Line 40: | Line 52: | ||
The GU routines use hardware to perform drawing operations for you. Note that you can draw to different locations, such as a memory buffer or to the framebuffer, in the latter case you'll see the result on screen. This also means it is possible to combine page flipping with hardware assisted drawing, and there's GU routines to help with this. It is important to note that since the GPU is drawing stuff the CPU are free to do other things, also note that you have to consider that the CPU doesn't know what the GPU is doing and vice versa. Because of cache, all textures, vertex lists and such must be in memory before you use them. This means you use a function to invalidate the cache for those memory regions causing any cached data to be written to memory. Again the same data also needs to be in a memory address that is a multiple of 16 bytes, but if you use GU routines to allocate the memory they will take care of this for you. Textures need to be swizzled as well. | The GU routines use hardware to perform drawing operations for you. Note that you can draw to different locations, such as a memory buffer or to the framebuffer, in the latter case you'll see the result on screen. This also means it is possible to combine page flipping with hardware assisted drawing, and there's GU routines to help with this. It is important to note that since the GPU is drawing stuff the CPU are free to do other things, also note that you have to consider that the CPU doesn't know what the GPU is doing and vice versa. Because of cache, all textures, vertex lists and such must be in memory before you use them. This means you use a function to invalidate the cache for those memory regions causing any cached data to be written to memory. Again the same data also needs to be in a memory address that is a multiple of 16 bytes, but if you use GU routines to allocate the memory they will take care of this for you. Textures need to be swizzled as well. | ||
+ | |||
+ | === Display Lists === | ||
+ | Drawing graphics can be done by hitting VRAM directly, for decent performance and 3D work you need to use the display lists. | ||
+ | * Each entry in the display list is 32-bits wide: 8-bits command, 24-bits data | ||
+ | * 24bit data can represent an integer, a pointer or a cut down float | ||
+ | * Can create sub-lists and which are called from your main list | ||
+ | * Can specify custom vertex types, different size (8/16-bit fixed point, 32-bit float) | ||
+ | * Each vertex type can include, position, colour, normal or weight | ||
+ | * Vertices can be specified as a direct list or indexed | ||
+ | * Due to floats only being 24bit precision can be lost during transformation stage | ||
+ | |||
+ | The display lists are transferred to the GE using a DMA mechanism, this has important ramifications when developing the lists. | ||
+ | * A list can be transferred while building it using a 'Stall' address | ||
+ | * The list must be written using an uncached memory area or the datacache written back before use | ||
+ | * Lists should be terminated with a FINISH command | ||
+ | |||
+ | <syntaxhighlight lang="c"> | ||
+ | uint32_t list [256∗1024]; //Define a display list | ||
+ | |||
+ | int qid = sceGeListEnQueue(list, list, cbid, NULL); | ||
+ | /∗ Fill in the dispay list ∗/ | ||
+ | sceKernelDcacheWritebackInvalidateAll(); //Writeback cache | ||
+ | sceGeListUpdateStallAddr(qid, &list[endp]); | ||
+ | </syntaxhighlight> | ||
=== Developing VFPU Code === | === Developing VFPU Code === | ||
Line 64: | Line 100: | ||
== Tutorials == | == Tutorials == | ||
+ | * [[PSP texture swizzling]] | ||
== Resources == | == Resources == | ||
+ | * [http://www.darkhaven3.com/psp-dev/wiki/index.php/Main_Page PSP Dev Wiki] - an actual not-archived resource | ||
* http://hitmen.c02.at/files/yapspd/psp_doc/index.html#idx27.1 | * http://hitmen.c02.at/files/yapspd/psp_doc/index.html#idx27.1 | ||
* http://forums.dashhacks.com/psp-programming-development/267111-psp-gu-tutorials-initializing-gu.html | * http://forums.dashhacks.com/psp-programming-development/267111-psp-gu-tutorials-initializing-gu.html | ||
Line 74: | Line 112: | ||
* OSLib_modv2 documentation http://dogo.github.io/oslibmodv2/ | * OSLib_modv2 documentation http://dogo.github.io/oslibmodv2/ | ||
* OSLib_mod documentation http://www.sakya.it/OSLib_MOD/doc/html/ | * OSLib_mod documentation http://www.sakya.it/OSLib_MOD/doc/html/ | ||
+ | * [https://uofw.github.io/upspd/docs/software/naked_psp.pdf Naked PSP] |
Latest revision as of 23:24, 22 October 2020
The PSP kernel is built up of multiple separate "Modules"; it is not a monolithic kernel in the usual sense. User applications are also considered modules, and modules can be loaded and started almost at will. They can be loaded to fixed locations or relocatable locations, and can export and import functions from other modules
The PSP kernel has no real concept of a "process" as you would find in other operating systems.
Contents
Executable Formats
The PSP uses the Executable and Linking Format (ELF) as the base for its modules, but can load the following types of files natively:
- ELF - Basic ELF format linked to a hardcoded address (typically 0x8900000)
- PRX - Customized ELF format, can be relocated anywhere in memory space
- ~PSP - An encrypted wrapper format for ELF or PRX
While the PSPSDK can produce ELF or PRX formats, it cannot produce the proprietary encrypted ~PSP format.
Graphics
Note that while pixel depths are referred to by RGBA below, the actual bit order is BGRA (or BGR for formats without alpha).
Color format is adjustable, but display resolution is fixed when using the PSP display.
Pixel Formats
PSP_DISPLAY_PIXEL_FORMAT_8888
- 32-bit RGBA 8:8:8:8 - Full 24-bit color with 8-bit alpha, uses double the VRAMPSP_DISPLAY_PIXEL_FORMAT_4444
- 16-bit RGBA 4:4:4:4 - 12-bit colors, plus 4-bit alphaPSP_DISPLAY_PIXEL_FORMAT_5551
- 16-bit RGBA 5:5:5:1 - 5 bits per color channel, plus boolean alpha (1-bit)PSP_DISPLAY_PIXEL_FORMAT_565
- 16-bit RGBA 5:6:5 - Slightly wider color gamut by bumping green bits to 6, with red and blue using 5 bits
Drawing Pixels
If you're just pushing raw pixels to the screen, there are two ways to do it. There's direct access to the framebuffer:
u32* vram = (u32*)0x44000000;
sceDisplaySetFrameBuf((void*)vram, 512, PSP_DISPLAY_PIXEL_FORMAT_8888, PSP_DISPLAY_SETBUF_IMMEDIATE);
The VRAM address is 0x04000000
, changing the address into 0x04000000
means that reads and writes are uncached. This is slower, but has the advantage that you don't have to sync the cache manually and you're less likely to see graphic artifacts. You can use other memory locations for the framebuffer as well, but the address must be a multiple of 16 bytes.
Calling sceDisplaySetMode()
before drawing is also recommended. The code above is for 32-bit mode (8 bits per channel), but other modes are available. Even though the PSP screen is 480 pixels wide, the framebuffer is usually 512 pixels wide to allow for faster address calculation, and as a result faster drawing.
Some of the hardware assisted features you can do with framebuffer include vertical scrolling and page flipping.
Or you can create an array of vertices and draw them using the GPU:
typedef struct {
short unsigned u, v;
short x,y,z;
} Vertex;
Vertex*v=sceGuGetMemory(1*sizeof(Vertex));
v[0].u=0;
v[0].v=0;
v[0].x=240;
v[0].y=136;
sceGuDrawArray(GU_POINTS,GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D,1,0,v);
The GU routines use hardware to perform drawing operations for you. Note that you can draw to different locations, such as a memory buffer or to the framebuffer, in the latter case you'll see the result on screen. This also means it is possible to combine page flipping with hardware assisted drawing, and there's GU routines to help with this. It is important to note that since the GPU is drawing stuff the CPU are free to do other things, also note that you have to consider that the CPU doesn't know what the GPU is doing and vice versa. Because of cache, all textures, vertex lists and such must be in memory before you use them. This means you use a function to invalidate the cache for those memory regions causing any cached data to be written to memory. Again the same data also needs to be in a memory address that is a multiple of 16 bytes, but if you use GU routines to allocate the memory they will take care of this for you. Textures need to be swizzled as well.
Display Lists
Drawing graphics can be done by hitting VRAM directly, for decent performance and 3D work you need to use the display lists.
- Each entry in the display list is 32-bits wide: 8-bits command, 24-bits data
- 24bit data can represent an integer, a pointer or a cut down float
- Can create sub-lists and which are called from your main list
- Can specify custom vertex types, different size (8/16-bit fixed point, 32-bit float)
- Each vertex type can include, position, colour, normal or weight
- Vertices can be specified as a direct list or indexed
- Due to floats only being 24bit precision can be lost during transformation stage
The display lists are transferred to the GE using a DMA mechanism, this has important ramifications when developing the lists.
- A list can be transferred while building it using a 'Stall' address
- The list must be written using an uncached memory area or the datacache written back before use
- Lists should be terminated with a FINISH command
uint32_t list [256∗1024]; //Define a display list
int qid = sceGeListEnQueue(list, list, cbid, NULL);
/∗ Fill in the dispay list ∗/
sceKernelDcacheWritebackInvalidateAll(); //Writeback cache
sceGeListUpdateStallAddr(qid, &list[endp]);
Developing VFPU Code
The 128 32-bit VFPU registers are reconfigurable to operate as single values, 2x2/3x3/4x4 rows, columns, matrices, or transposed matrices. The stored matrices can be multiplied in a single operation. The usual selection of trigonometric/square root instructions is available.
The VFPU also has an on-board pseudo-random number generator.
VFPU code is written in assembly, and the PSP build toolchain supports all known VFPU operations.
/∗ Multmatrix $a0−result, $a1−a, $a2−b ∗/
multmatrix :
/∗ Load matrices to internal registers ∗/
ulv.q C000, 0($a1); ulv.q C010, 16($a1)
ulv.q C020, 32($a1); ulv.q C030, 48($a1)
ulv.q C100, 0($a2); ulv.q C110, 16($a2)
ulv.q C120, 32($a2); ulv.q C130, 48($a2)
/∗ Multiply matrices∗/
vmmul.q M200, M000, M100
/∗ Store result */
usv.q C200, 0($a0); usv.q C210, 16($a0)
usv.q C220, 32($a0); usv.q C230, 48($a0)
Tutorials
Resources
- PSP Dev Wiki - an actual not-archived resource
- http://hitmen.c02.at/files/yapspd/psp_doc/index.html#idx27.1
- http://forums.dashhacks.com/psp-programming-development/267111-psp-gu-tutorials-initializing-gu.html
- http://forums.dashhacks.com/psp-programming-development/267986-psp-gu-tutorials-vertex-structures.html
- https://web.archive.org/web/20110201004634/http://www.psp-programming.com/tutorials/
- OSLib https://web.archive.org/web/20100412060727/http://www.psp-hacks.com/forums/f141/how-to-create-games-and-apps-on-your-t153653/post478381.html
- OSLib_modv2 https://github.com/dogo/oslibmodv2
- OSLib_modv2 documentation http://dogo.github.io/oslibmodv2/
- OSLib_mod documentation http://www.sakya.it/OSLib_MOD/doc/html/
- Naked PSP