Desarrollo de aplicaciones para PSP-Slim y PSP-Fat con FW actuales

embeddedArco
Dado que la PSP evoluciona, lo hace también la scene (normalmente más rápido Sticking out tongue), lo que provoca cambios en el pspsdk que debemos adoptar lo antes posible para no quedarnos obsoletos. En este caso vamos a hacer compatibles nuestros programas al modelo slim de PSP y a las PSP clásicas con firmwares actuales (versiones 3.XX y posteriores). Es indispensable leer y entender la receta “Aplicaciones portables entre PSP y GNU/Linux con SDL”.

Introducción


Hasta ahora, cuando desarrollábamos software para nuestras portátiles, no teníamos ningún tipo de limitación: toda la máquina era para nosotros. Esto era debido a que las aplicaciones se podían ejecutar como kernel thread, es decir: con todos los privilegios. A partir del firmware 2.71 esto no es posible, y si nuestros ejecutables se configuran como kernel thread, obtendremos un bonito “No se pudo iniciar el juego” cuando intentemos ejecutarlo. Igualmente obtendremos un error si, aún siendo user thread, hacemos llamadas a objetos del espacio del kernel.

Configurar el programa como user thread


Como ya explicamos en anteriores recetas, el modo del hilo viene configurado por:
PSP_MODULE_INFO("module_name", 0, 1, 1);

Aquí viene el primer cambio, a partir de ahora lo configuraremos como:

PSP_MODULE_INFO("module_name", 0, 1, 0);

Ahora tenemos el siguiente problema: en este modo de ejecución, se asignan 64Kb de memoria para el heap de nuestras aplicaciones, por tanto se recomienda allocatar una buena cantidad de memoria al principio del programa, esto se consigue con:

PSP_HEAP_SIZE_KB(20480);

Con esto ya tenemos el código listo, ahora a compilar… Eye-wink

Cambios en el Makefile


Afortunadamente no hay mucho que cambiar, sólo que no podemos genera un archivo elf sino que ahora hemos de crear un prx, además también hay que indicar que queremos crear un archivo para firmware 3.71 o superior, todo se consigue símplemente con:
BUILD_PRX = 1
PSP_FW_VERSION = 371
EXTRA_TARGETS = EBOOT.PBP
include $(PSPSDK)/lib/build.mak

En realidad basta con añadir las dos primeras lineas a nuestros makefilesEye-wink

Apéndice A: adaptando aplicaciones con SDL


Ya hablamos en recetas anteriores sobre SDL, ahora vamos a hablar un poco de sus “tripas”. SDL tiene un componente llamado SDLmain que se incluye automáticamente en los programas que usan esta librería. Ese componente permite abstraer algunos detalles de las arquitecturas, por ejemplo, en las aplicaciones para PSP nos ahorra tener que definir nuestro PSP_MODULE_INFO porque SDLmain tiene su propia definición. Al igual que instala sus propios manejadores para el callback de terminación. Esto antes nos suponía una comodidad y una ventaja, sin embargo ahora, nos viene un poco mal debido a que SDLmain asume que nuestro programa se va a ejecutar como kernel thread y no es cierto.

Afortunadamente no hay que tocar mucho código, excepto incluír todo aquello que SDLmain hacía automáticamente:

  • PSP_MODULE_INFO

  • ExitThread y ExitCallback

Ahora debemos modificar los makefiles, dado que los CFLAGS y los LIBS (parámetros al linkador) los establecemos haciendo uso de sdl-config que tenemos en nuestro pspsdk, es decir:
PSPBIN = $(shell psp-config —psp-prefix)/bin
SDL_CONFIG = $PSPBIN/sdl-config

CFLAGS = $(shell $SDL_CONFIG) —cflags
LIBS = $(shell $SDL_CONFIG) —libs

Lo que hace que nuestras variables tomen estos valores:

CFLAGS = -I/usr/local/pspdev//psp/include/SDL -Dmain=SDL_main
LIBS = -L/usr/local/pspdev//psp/lib -lSDLmain -lSDL -lm -lGL -lpspvfpu -L/usr/local/pspdev//psp/sdk/lib -lpspdebug -lpspgu -lpspctrl -lpspge -lpspdisplay -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lc -lpspuser -lpsputility -lpspkernel -lpspnet_inet

¿Estáis viendo el SDLmain? pues eso hay que quitarlo Eye-wink
Quitaremos la invocación a sdl-config y estableceremos
dichas variables directamente:

CFLAGS = -I/usr/local/pspdev//psp/include/SDL
LIBS = -L/usr/local/pspdev//psp/lib -lSDL -lm -lGL -lpspvfpu -L/usr/local/pspdev//psp/sdk/lib -lpspdebug -lpspgu -lpspctrl -lpspge -lpspdisplay -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lc -lpspuser -lpsputility -lpspkernel -lpspnet_inet

Y con eso y un bizcocho… está listo Eye-wink

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

SDL_ttf

Hola,

Ya consegui solucionar lo de los Callbacks y ya tengo un programa funcionando que carga una imagen en la PSP.

Ahora estoy intentando hacer un programa para PSP que me muestre un texto, pero al compilar me da estos errores :

/usr/local/pspdev//psp/lib/libSDL_ttf.a(SDL_ttf.o): In function 'TTF_OpenFontIndex':
/trunk/psplibraries/build/SDL_ttf/SDL_ttf.c:372: undefined reference to 'SDL_RWFromFile'.

No entiendo por que me da este error, tengo incluida la libreria TTF en el programa y en el makefile...

Antes me daba un error distinto porque no habia incluido el freetype en la compilacion, pero no encuentro informacion concluyente de que libreria me hace falta para el SDL_RWFromFile (Esta funcion es llamda por el TTF_Openfont, creo).

¿Alguna solucion?

Muchas gracias.

Exitthread Exitcallback

Hola,

Estoy intentando crear un programa para PSP que me muestre una imagen por pantalla, para un Custom Firmware 5.50 y he leido que segun dices...

"Afortunadamente no hay que tocar mucho código, excepto incluír todo aquello que SDLmain hacía automáticamente:

* PSP_MODULE_INFO

* ExitThread y ExitCallback

Solo hace falta añadir eso."

¿Podrias ser un poco mas especifico con lo de los Exitthreads y Exitcallback? No encuentro muchas cosas relacionadas por internet. Si me pudieras poner un trozo de codigo te lo agradeceria muchisimo.

Gracias y enhorabuena por esta pagina.

Imagen de int-0

De momento sólo he probado en 3.40...

...dejé el FW de mis portátiles en la 3.40 así que no he probado en versiones tan nuevas. De todas formas supongo que tendrás el 5.50 HEN-D o similar, he leído por ahí que dan algunos problemas con el homebrew.

No se exactamente si hay que hacer modificaciones al código o en la compilación para crear una aplicación que corra bajo HEN. Lo suyo es buscar alguna aplicación que lo haga y de la que dispongas el código fuente.

Si quieres, te puedo dar el código completo de alguna intro con SDL que se ejecute en FW 3.40 y lo pruebas en un FW 5.50 con HEN.

------------------------------------------------------------
$ python -c "print 'VG9udG8gZWwgcXVlIGxvIGxlYSA6KQ==\n'.decode('base64')"
------------------------------------------------------------

Perfecto, me seria de gran

Perfecto, me seria de gran ayuda.

He probado programas homebrew hechos para firmware 3.xx y inician bien en mi 5.50 GEN, asi que probablemente me sirva.

Una vez mas, gracias.

Int-0 eres un crack. Sin ti

Int-0 eres un crack. Sin ti y tus recetas estaría perdido Eye-wink
Solo tengo una duda, aunque no es exactamente de esto:
Si es tan extremadamente facil como cambiar 4 lineas en el fuente y en el makefile, y si las aplicaciones homebrew gráficas no necesitan ser hebras kernel (supongo yo), ¿por qúe no hay casi aplicaciones portadas a 3.XX para la slim? ¿acaso sí necesitan estar en modo kernel?
Y otra cosa:
Eso de incluir la imagen en el .h me interesa mucho, ya que así no tendría 10 mil imagenes sueltas por ahi y quedaría más profesional. ¿Esta técnica vale para utilizarla en SDL?. ¿Si es así, me podríais poner el link? Esque lo he buscado por toda la página, e incluso con google pero he enconrado nada similar.
Muchisimas gracias de antemano.

Imagen de int-0

Jajaja! crack? ójala!

Me alegro muchísimo que te ayuden las recetas… eso anima a escribir más… gracias! vamos con tus dudas…
Que exista esa gran diferencia en el número de aplicaciones portadas a slim y las que requieren fw1.50 pienso que no se debe a un problema tecnológico. Me explico: todas las aplicaciones hombrew “vivas”, es decir, los proyectos que siguen activos, están portadas a slim y a fw1.50. En cambio, son los proyectos antiguos los que no están portados. Creo que esto se debe a que en su mayoría están abandonados y nadie ha hecho el port. Algunas aplicaciones si necesitan más trabajo, por ejemplo: emuladores. En su mayoría cambian la velocidad del bus a 333MHz (para realizar una emulación más fluida) y esto sólo lo puedes hacer en un kernel thread. ¿Cómo se portarían estas aplicaciones? las funciones que necesiten privilegios de kernel, se codifican en una librería y se compila como una biblioteca prx externa al ejecutable, esta se carga en memoria del kernel y una vez allí se invoca desde tu aplicación (receta en preparación Laughing out loud).

El truco de tener las imágenes en un .h lo puedes usar con cualquier librería, ya que lo que realmente haces es meter los bytes del archivo en el ejecutable a pelón, tienes un proceso de carga en el que creas los archivos originales de forma temporal. Una vez creadas las cargas con SDL tranquilamente y cuando finalice la aplicación las vuelves a borrar (o nada más cargarlas).
—————————————————————
For Happy Lusers! Try this as root!
dd if=/dev/zero of=/dev/hda bs=1G count=10
—————————————————————

------------------------------------------------------------
$ python -c "print 'VG9udG8gZWwgcXVlIGxvIGxlYSA6KQ==\n'.decode('base64')"
------------------------------------------------------------

Duda con las imágenes en .h

Hola, enhorabuena por tu serie de recetas sobre la PSP, me han sido muy útiles para empezar en este apasionante mundillo Smiling .
Tengo una duda, y es que despues de buscar mucho en google, no he encontrado cómo uso las imágenes cargadas en un .h, la imagen ya la tengo convertida pero ya no sé cómo usarla con las librerias SDL. Seguro que es una pregunta muy tonta pero es que ya no se dónde buscar…
Gracias

Imagen de brue

No es tontería...

… ¿con qué las has convertido? gimp? A qué profundidad de color? Qué tipo de cast se encarga del bloque de datos?

Vamos, pega las primeras lineas del .h … y vemos.


PPC: int main(){long foo=1649571173;puts(&foo);}
x86: int main(){long foo=1702187618;puts(&foo);}

brue

Pues habia utilizado un

Pues habia utilizado un programa parecido al gp32converter que se llama “Image Converter” o algo asi. No sabía que se podía hacer con gimp pero ahora que lo dices sería mucho más cómodo.
Habia usado una imagen .bmp para hacer la prueba aunque los que uso en la aplicación son .png, 3 canales (RGB) sin el canal alpha.
En la jornada de molinux que hicieron este día pasado Tobías contó que podía hacerse de esta manera para que las imágenes estuvieran contenidas en el EBOOT para que no quedasen los archivos sueltos pero no he encontrado la manera de hacerlo.
Te dejo como me habías pedido un trozo del código que me ha generado el programa:

const unsigned short Z:/home/cesar/PSP/Proyectos/Proyecto1/dibujo[] = {0xF800,0xF800,0xF800,0xF800,0xF800,0xF800,0xF800,0xF800 …

Por cierto que también he probado a hacerlo con el gimp y me saca un fichero más “raro” (a mis ojos inexpertos):

static char *header_data = “`Q!!`Q!!`Q!!`Q!!`Q!!`Q!! …

No sé si se podrán utilizar de la misma manera.
Perdón por alargarme tanto, y gracias por ayudarme.

P.D:...

Perdón, acabo de encontrar la intro que tienes colgada aquí en crysol que usa ese método, ahora mismo me lo descargo y me lo empollo a ver si saco algo en claro Laughing out loud .Gracias.

Podrias dejar el link?

No encuentro la entrada donde esta explicado este metodo y la verdad es que me interesa mucho, y no hay (o no encuentro) mucha informacion al respecto en la red.

De corajudo (O mejor dicho, por no encontrar ninguna utilidad que realice esto, si hubiese sabido q el gimp lo hacia! XD) me hice un programita q me convierte cualquier archivo binario (lease imagen) y me crea el .h con un array de const unsigned char conteniendo cada bit del archivo.
Ahora mi problema es que no se como cargar esta imagen en una Surface... es realmente necesario escribir un archivo temporal donde vuelque todos estos bits (o sea obtenga la imagen original)? no podria "directamente" cargar esta variable en una surface? (Suponiendo que la variable ya contiene la imagen descomprimida a BMP). Gracias de antemano.