[Manual] Programación en C para PSP

Moderadores: Kravenbcn, largeroliker, fidelcastro, cerealkiller, pspCaracas, dark_sasuke, m0skit0, LnD, ka69, zacky06

Avatar de Usuario
Alek
ViP Hordes
ViP Hordes
Mensajes: 89
Registrado: 19 May 2010, 19:16
PSN ID: PlayAlek
Contactar:

[Manual] Programación en C para PSP

Mensaje por Alek »

En esta entrada, analizaremos paso a paso, y sin dejarnos nada en el tintero, cómo programar en C para PSP. Pasaremos por lo básico y terminaremos por lo más avanzado, por lo que muchas veces no acaba de convencer, o esas cosas que no se enseñan en cualquier sitio.

No diré que este es un manual no adecuado para newbies, n00bs o novatos, ya que sí lo es, pues se tocará desde el principio. Sin embargo, si nunca habéis programado en C o algún lenguaje pseudovisual, lo tendréis algo complicado. De esta manera, y como no podría ser de otra manera, es necesario conocer algo de programación, al menos para no desorientarse demasiado. La práctica viene luego.

Considerando la amplitud que va a conllevar este manual, y que no es la primera vez que copian algo que he escrito, rogaría que antes de copiar algo (que será asignado a este sitio, DaxHordes.org), se me comunique via PM por este mismo sitio... respetando siempre la licencia GPLv3 que se puede consultar aquí. Con ello no intento impedir que alcance otros sitios (y con ello más ojos), sino simplemente intento llamar a la conciencia, aunque no siempre conlleve el éxito que cualquiera podría desear.

Como muchos sabréis, he intentado muchas veces llegar a hacer un manual como este, y aunque en Dark-AleX.org llegué a publicar un manual de hasta seis lecciones, no llegaba a estar completo, no aún. Es por ello, que al fin y al cabo, considero que este manual es una de esas herencias de esa página que no deben quedarse en el olvido.

Más allá de explicar cómo poner en funcionamiento todo el meollo, me interesa especialmente hacer referencias completas a cada herramienta según vaya siendo necesario. De esa manera, este manual tendrá un progreso continuado referiéndose acerca del cómo preparar todo el entorno, y cómo funcionar con él. Y, de entre medias de todo eso, tendremos la oportunidad de desgranar cada herramienta y cada determinante que nos haga falta.

Revisiones del Documento

02/06/2010 v0.2 Primer borrador público. Completado hasta lo que se dio antiguamente con correcciones, ampliaciones y actualizaciones.
xx/xx/xxxx v0.1 Primer borrador. Privado.


Índice

[*] Los Requisitos.
[*] Instalación del Entorno de Programación bajo Windows.
[*] Instalación del Entorno de Programación bajo GNU/Linux.
[*] Instalación de las Librerías no oficiales.
[*] Herramientas: PRXtool.
[*] Herramientas: PSARdumper.
[*] Herramientas: PSPLinkUSB.
[*] Herramientas: NIDattack.
[*] Herramientas: PRXdecrypter.
[*] Estructura Básica: main.c y Makefile.
[*] Librerías Oficiales: pspDebug y pspDisplay.
[*] Hola, Mundo!.
[*] Librerías Oficiales: pspCtrl.
[*] Librerías Oficiales: pspUmd.
[*] Librerías Oficiales: pspIoFileMgr.
[*] Librerías Oficiales: pspUsb
[*] Librerías Oficiales: pspNet
[*] Librerías Oficiales: pspPower
[*] Librerías Oficiales: pspNand_Driver
[*] Librerías Oficiales: pspIdStorage
[*] Librerías Oficiales: pspKernel
[*] Librerías No Oficiales:
[*] Apéndice: ELF y PRX. Explicación y Creación.
[*] Apéndice: Creación de Librerías
[*] Apéndice: Uso de la Librería VLF 1.0


Los Requisitos:

Spoiler:
[*] Sistema Operativo: Windows o GNU/Linux. En este manual, usaremos Windows XP y Ubuntu 10.04.
[*] Una conexión a internet (ADSL o mejor)
[*] Litros de "paciencia". :pinta:



Instalación del Entorno de Programación bajo Windows

Spoiler:
En este apartado, aprenderemos acerca de cómo preparar nuestro entorno de programación para programar en C para PSP bajo un sistema operativo Windows (XP SP3, en nuestro caso).

Obviamente, antes de comenzar deberemos tener actualizado nuestro Windows y sin problemas de compatibilidades, con tal de minimizar los riesgos de errores que podamos tener.

Al fin y al cabo, para programar es interesante (pero debería ser obligatorio) tener siempre un entorno GNU/Linux, y en nuestro caso no va a ser distinto. Suponiendo, sin embargo, que tengamos Windows y no nos queramos mover de él, tendremos que hacer un poco más de trabajo para poder manejar el compilador.

En este sentido, necesitaremos de un emulador de la misma estructura de GNU/Linux, llamado Cygwin. Gracias a él, podremos tener un gran número de herramientas necesarias de GNU/Linux, pero sin estar en dicho sistema operativo.

En primer lugar, pues, descargamos el ejecutable de Cygwin y lo ejecutamos para instalarlo. (En el caso de Windows Vista y superior, tendréis que ejecutarlo como Administrador y/o con permisos del UAC). Su instalación es bastante sencilla, por lo que limítate a seguir los pasos que aparecen señalados en las siguientes imágenes:
setup.7z

1.PNG

2.PNG

3.PNG

4.PNG

5.PNG

6.PNG

7.PNG

8.PNG


Como veis, seleccionamos una ruta (en nuestro caso el Escritorio) donde dejar los archivos temporales de instalación que descargue, y una dirección-espejo de donde bajar los archivos que sea relativamente cercana a nuestra localización (en nuestro caso uno francés).

Al terminar con esos pasos, nos aparecerá esta ventana:
9.PNG

donde podemos ver cómo nos lista la serie de paquetes que podemos instalar mediante este programa.

Pues bien, a efectos prácticos para nuestro toolchain y sdk, nos harán falta los siguientes paquetes:

Código: Seleccionar todo

autoconf, automake, bison, flex, gcc, gmp, libtool, libusb-dev, make, mpfr, ncurses, patch, readline, subversion, texinfo, wget

Nota: Aquí nos faltarían algún que otro paquete para poder compilar la documentación conjunta, mediante graphviz y doxygen. Sinceramente, yo suelo siempre instalar el "paquete completo", pero ya que no es necesario para esto, nos adecuaremos a lo necesario.

Para poder seleccionar los paquetes que necesitamos, o bien buscamos uno por uno y hacemos click en la instalación de los binarios, o bien instalamos todo el paquete "Base" y "Devel", así como el paquete "wget" de "Web". De cualquier manera, y aunque por lo general todos los anteriormente mencionados se incluyen por defecto, siempre es interesante revisar y buscar uno a uno para confirmar que tenemos todos y, en caso contrario, disponerlos para tal efecto.

Ahora bien, dejamos que descargue - instale - ejecute cada comando (tardará un buen rato dependiendo del sitio de descarga que hayamos elegido anteriormente), y una vez terminado disponemos un acceso directo al escritorio y damos por finalizada la instalación de este emulador.

Ahora bien, aún nos queda prácticamente todo el trabajo. Al ejecutar por primera vez nuestro emulador Cygwin, veremos lo siguiente:
10.PNG

de manera que nuestra instalación, como vemos, del emulador se ha completado sin problema.

Hagamos una breve parada.

Como sabemos, para poder programar en cualquier plataforma, es necesario un set de herramientas llamado Toolchain y un Development Kit (SDK) que incluye las librerías y demás asuntos que son necesarios para poder programar, incluído un compilador, un debugger, un interpretador, y demás detalles.

Debido a que como es lógico no disponemos de las herramientas oficiales de Sony, tendremos que usar unas libres, que fueron desarrolladas desde las oficiales (mediante ingeniería inversa sobre un juego relativamente antiguo) y que están a disposición de todos de forma gratuita, desde ps2dev.org

Para poder hacernos con ellas, tendremos que acceder al SVN de dicho servidor, y descargar a priori el Toolchain (que nos incluye el SDK de igual manera) mediante el siguiente comando:

Código: Seleccionar todo

svn co svn://svn.ps2dev.org/psp/trunk/psptoolchain

desde Cygwin, como vemos, terminando de esta manera:
11.PNG


Ahora bien, y como en cualquier SVN, si queremos actualizar lo que nos hemos descargado en el futuro, nos bastará con acceder a la susodicha carpeta, y:

Código: Seleccionar todo

cd trunk
svn update

teniendo de dicha manera unas fuentes siempre actualizadas (aunque para actualizar todo en verdad haría falta el reinstalarlo, pero vamos, es lo que veremos ahora.

Nota: Es interesante revisar de vez en cuanto este subforo de ps2dev.org, donde se puede por uno propio ver o comentar posibles parches o cambios que efectivamente hacen una disposición directa en lo que trabajamos. Y que, al fin y al cabo, provocarán nuestras actualizaciones.

Sin embargo, antes de ponerse a ejecutar el script de instalación, hay que definir la rutina de entrada mediante la edición del archivo .bashrc que se encuentra en la siguiente ruta: (antes de editarlo, cerramos Cygwin)

Código: Seleccionar todo

C:\cygwin\home\<nombre.de.usuario>\

añadiendo, al final del archivo, las siguientes líneas:

Código: Seleccionar todo

#PSP SDK
export PSPDEV=/usr/local/pspdev
export PATH=$PATH:$PSPDEV/bin

dejando una línea en blanco al final. Una vez terminada y guardada la edición, reabrimos Cygwin.

Nota: Es imprescindible el usar un editor neutro para la edición de este archivo. Con esto me quiero referir a un editor que no incluya ningún tipo de formateo, como suele hacer Wordpad o Word. Para ello, y como opción interesante, aconsejo uno de los editores que más me gustan, el Notepad++ que uso para programar en otros sistemas.
npp.5.6.8.Installer.exe.7z


Como recordais, a la hora de instalar Cygwin hemos instalado una serie de paquetes, entre los que se encuentra "gmp" y "mpfr". Sin embargo, habitualmente suele dar errores de instalación, como vemos aquí, al intentar ejecutar el script de instalación:

Código: Seleccionar todo

ls: cannot access /usr/include/gmp.h: No such file or directory
ERROR: Install gmp before continuing.
../depends/check-gmp.sh: Failed.

así como con el otro que hemos hablado, el mpfr.

Para poder solucionar esto, tendremos que instalar esos dos paquetes a mano, todo por comandos, como sigue:

Código: Seleccionar todo

wget ftp://ftp.gmplib.org/pub/gmp-5.0.1/gmp-5.0.1.tar.gz
tar xzvf gmp-5.0.1.tar.gz
cd gmp-5.0.1
./configure
make
make check
make install
cp /usr/local/include/gmp.h /usr/include

Código: Seleccionar todo

wget http://www.mpfr.org/mpfr-current/mpfr-2.4.2.tar.gz
tar xzvf mpfr-2.4.2.tar.gz
cd mpfr-2.4.2
export C_INCLUDE_PATH="/usr/local/include"
export LIBRARY_PATH="/usr/local/lib"
export LD_LIBRARY_PATH="$LIBRARY_PATH"
./configure
make
make check
make install
cp /usr/local/include/mpfr.h /usr/include

gmp-5.0.1.tar.gz

mpfr-2.4.2.tar.gz


Nota1: Es posible que, de la preparación de este manual a cuando tú lo uses, la versión e incluso la ruta del archivo haya cambiado. Para solucionar esto, revisa la página oficial y haz el mismo proceso, pero para el archivo más nuevo.

Nota2: Si al instalar da un error en que no encuentra ncurses a pesar de tenerlo instalado con anterioridad via Cygwin, tendremos que editar el archivo psptoolchain/depends/check-ncurses.sh y cambiar la línea:

Código: Seleccionar todo

ls /usr/include/ncurses.h 1> /dev/null || { echo "ERROR: Install ncurses before continuing."; exit 1; }

por:

Código: Seleccionar todo

ls /usr/include/ncurses/ncurses.h 1> /dev/null || { echo "ERROR: Install ncurses before continuing."; exit 1; }

debido a un error en la definición de parámetros.

Una vez listo, ejecutamos el script de instalación de la siguiente manera, accediendo a la carpeta anteriormente descargada:

Código: Seleccionar todo

cd psptoolchain
./toolchain.sh

cuando haya terminado (dadle bastante tiempo), volvereis a la entrada inicial.

Con esto, ya tendremos listo nuestro entorno de desarrollo... al menos la parte fundamental.



Instalación del Entorno de Programación bajo GNU/Linux

Spoiler:
Ahora, vamos a ver cómo hacer lo mismo que en el apartado anterior, pero bajo GNU/Linux. Algo que, sin duda, vereis cómo es mucho más simple y sencillo.

Para ello, necesitaremos del uso de la Terminal, asi que quienes no estéis demasiado acostumbrados a ella, más os vale poneros las pilas. En este manual, usamos Ubuntu 10.04, una instalación limpia. Esto quiere decir que instalaremos todos los paquetes necesarios, aunque puede que algunos ya los tengan instalados una u otra persona.

No repetiré las mismas palabras que en el apartado anterior, de manera que si quereis algo de trasfondo quizás os resulte interesante leer el mismo de igual manera. Lo bueno es que, a diferencia de ese, no tendremos que instalar ningún emulador, pues trabajaremos nativamente sobre Linux.

A priori, tenemos que descargar e instalar los paquetes necesarios del sistema para poder compilar todo lo que vamos a utilizar. De esta manera, y considerando de nuevo que es una instalación limpia y nueva, dispondremos el siguiente comando:

Código: Seleccionar todo

alex@Hesperia:~$ sudo apt-get install build-essential autoconf automake1.9 bison flex libncurses5-dev libreadline-dev libusb-dev texinfo subversion libgmp3-dev libmpfi-dev libmpfr1ldbl libmpfr-dev autogen libtool graphviz doxygen g++


Nota: Es posible que, desde la fecha de la creación de este manual hasta que lo uses personalmente, alguno de los nombres de los paquetes hayan cambiado, y no te los encuentren con tal nombre; sobretodo si usas otra versión o distribución de GNU/Linux.

Luego, tenemos que hacer como anteriormente, bajar los archivos necesarios de ps2dev.org;

Código: Seleccionar todo

alex@Hesperia:~$ mkdir psp
alex@Hesperia:~$ cd psp
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/psptoolchain


Nota1: Es posible que, al hacer el "co" o "checkout" del SVN, es decir, al revisar e intentar bajarse los archivos necesarios, de un timeout o no te lo permita por cualquier causa. Habitualmente, suele ser un problema del servidor, algo que se soluciona a base de paciencia.
psptoolchain.7z


Nota2: Tomad MUY buena nota de cuándo se usa el superusuario en GNU/Linux en este manual. No sería la primera ni la última vez que se confunden permisos, y al final la instalación se ha realizado desde un usuario normal pero en una carpeta de superusuario, sin que se pueda acceder a ella. Los comandos que aquí se presentan están comprobados y funcionan.

Y, antes de seguir con la instalación, tendremos que editar nuestra política de entrada mediante el archivo .bashrc,

Código: Seleccionar todo

alex@Hesperia:~/psp$ gedit ~/.bashrc

añadiendo, al final del mismo, lo siguiente:

Código: Seleccionar todo

# PSP SDK
export PSPDEV="/usr/local/pspdev"
export PSPSDK="$PSPDEV/psp/sdk"
export PATH="$PATH:$PSPDEV/bin:$PSPSDK/bin"

y a continuación guardando y cargando los cambios:

Código: Seleccionar todo

alex@Hesperia:~/psp$ source ~/.bashrc


Y continuamos con la instalación,

Código: Seleccionar todo

alex@Hesperia:~/psp$ cd psptoolchain/
alex@Hesperia:~/psp/psptoolchain$ sudo ./toolchain-sudo.sh


Teniendo, de esta manera (mucho más rápida y sencilla) todo el entorno instalado, bajo una simple terminal.

Nota: Es posible que, al finalizar la instalación, de un error simbólico en el último script referente al psplinkusb. Esta es una herramienta más que algo explícitamente necesario, de manera que no os preocupeis si da error, pues en un apartado futuro se explica el uso e instalación detallada de cada una de esas herramientas.

Toca una enésima parada, antes de concluir con lo anterior. Como hemos comentado en la sección de Windows, no hemos instalado una serie de librerías que nos ayudarían a compilar y crear la documentación adjunta creada con Doxygen para el PSPSDK.

Sin embargo, en esta ocasión, sí que lo hemos hecho. Por lo tanto, para poder compilar esa documentación, tendremos que acceder al directorio del pspsdk que bajamos junto al toolchain, y compilarla:

Código: Seleccionar todo

alex@Hesperia:~/psp/psptoolchain$ cd build
alex@Hesperia:~/psp/psptoolchain/build$ cd pspsdk
alex@Hesperia:~/psp/psptoolchain/build/pspsdk$ sudo doxygen -u doxygen.cfg
alex@Hesperia:~/psp/psptoolchain/build/pspsdk$ sudo make doxygen-doc

teniendo, de dicha manera, una documentación más que completa que perfectamente podemos subir a un servidor y usar de forma online, u offline. Aquí podeis descargar una copia.



Instalación de las Librerías no oficiales.

Spoiler:
A medida que se fue popularizando la programación para esta consola, una serie de librerías gratuitas no oficiales se fueron portando de poco a poco hacia este sistema, de manera que lo pudiera usar el propio procesador de la PSP.

Sin embargo, hay muchas de ellas cuyo uso se desconoce del todo, y por lo general se complementan con las oficiales, derivando en un uso menos problemático.

De entre estas, puede que la que más destaque sea la SDL con sus diferentes aplicaciones de gráficos, audio y demás, lo que conlleva la creación de aplicaciones más ricas en detalle, aunque esto implica aprender otro tanto desde cero.

Pues bien, la instalación de todas las librerías no oficiales, aunque se puede hacer de la siguiente manera:

Código: Seleccionar todo

 svn co svn://svn.ps2dev.org/psp/trunk/psplibraries
cd psplibraries
./libraries.sh

considero personalmente que, aunque sea más lento y metódico, es mejor ir instalando librería por librería, siempre que las necesitemos.

Por un lado, para poder descargar todas las librerías no oficiales podemos hacer directamente un:

Código: Seleccionar todo

svn co svn://svn.ps2dev.org/psp/trunk

aunque, de nuevo, es innecesario ya que nos devuelve más cosas de las que nos harán falta. Por lo tanto, iremos descargando a medida que necesitemos.

Nota: El orden aquí presentado es esencial, ya que hay muchas librerías que necesitan de otras para funcionar.
Nota2: Sólo instalad las que necesiteis, pues en otro caso es una pérdida de espacio y de tiempo.
Nota3: El uso y explicación de las librerías no oficiales (dentro del código) vendrá explicado más adelante.
Nota4: Aunque el proceso es el mismo en Windows, en este caso lo haré desde GNU/Linux ya que es significativamente más rápido. Los comandos, como digo, serán los mismos.

A la hora de instalar las librerías en GNU/Linux, es muy probable que nos encontremos con un problema de incompatibilidad de permisos entre los usuarios. De esta manera, tendremos que dar los permisos necesarios a /usr/local/pspdev/* para que podamos realizar operaciones de i/o, de la siguiente manera:

Código: Seleccionar todo

alex@Hesperia:~/psp/trunk/zlib$ sudo chmod a+rwx /usr/local/pspdev/psp/*


zlib

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/zlib
alex@Hesperia:~/psp$ cd zlib
alex@Hesperia:~/psp/zlib$ make
alex@Hesperia:~/psp/zlib$ make install

zziplib

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/zziplib
alex@Hesperia:~/psp$ cd zziplib
alex@Hesperia:~/psp/zziplib$ LDFLAGS="-L$(psp-config --pspsdk-path)/lib -lc -lpspuser" ./configure --host=psp --prefix=$(psp-config --psp-prefix)
alex@Hesperia:~/psp/zziplib$ make
alex@Hesperia:~/psp/zziplib$ make check
alex@Hesperia:~/psp/zziplib$ make install

sqlite

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/sqlite
alex@Hesperia:~/psp$ cd sqlite
alex@Hesperia:~/psp/sqlite$ LDFLAGS="-L$(psp-config --pspsdk-path)/lib -lc -lpspuser" ./configure --host=psp --disable-readline --disable-tcl --prefix=$(psp-config --psp-prefix)
alex@Hesperia:~/psp/sqlite$ make
alex@Hesperia:~/psp/sqlite$ make install

SDL

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/SDL
alex@Hesperia:~/psp$ cd SDL
alex@Hesperia:~/psp/SDL$ ./autogen.sh
alex@Hesperia:~/psp/SDL$ LDFLAGS="-L$(psp-config --pspsdk-path)/lib -lc -lpspuser" ./configure --host psp --prefix=$(psp-config --psp-prefix)
alex@Hesperia:~/psp/SDL$ make
alex@Hesperia:~/psp/SDL$ make install

SDL_gfx

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/SDL_gfx
alex@Hesperia:~/psp$ cd SDL_gfx
alex@Hesperia:~/psp/SDL_gfx$ ./autogen.sh
alex@Hesperia:~/psp/SDL_gfx$ AR=psp-ar LDFLAGS="-L$(psp-config --pspsdk-path)/lib -lc -lpspuser" ./configure --host psp --with-sdl-prefix=$(psp-config --psp-prefix) --prefix=$(psp-config --psp-prefix) --disable-mmx --disable-shared
alex@Hesperia:~/psp/SDL_gfx$ make
alex@Hesperia:~/psp/SDL_gfx$ make install

SDL_image

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/SDL_image
alex@Hesperia:~/psp$ cd SDL_image
alex@Hesperia:~/psp/SDL_image$ ./autogen.sh
alex@Hesperia:~/psp/SDL_image$ LDFLAGS="-L$(psp-config --pspsdk-path)/lib -lc -lpspuser" ./configure --host psp --with-sdl-prefix=$(psp-config --psp-prefix) --prefix=$(psp-config --psp-prefix)
alex@Hesperia:~/psp/SDL_image$ make
alex@Hesperia:~/psp/SDL_image$ make install

libogg

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/libogg
alex@Hesperia:~/psp$ cd libogg
alex@Hesperia:~/psp/libogg$ LDFLAGS="-L$(psp-config --pspsdk-path)/lib -lc -lpspuser" ./autogen.sh --host psp --prefix=$(psp-config --psp-prefix)
alex@Hesperia:~/psp/libogg$ make
alex@Hesperia:~/psp/libogg$ make install

libvorbis

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/libvorbis
alex@Hesperia:~/psp$ cd libvorbis
alex@Hesperia:~/psp/libvorbis$ LDFLAGS="-L$(psp-config --pspsdk-path)/lib -lc -lpspuser" ./autogen.sh --host psp --prefix=$(psp-config --psp-prefix)
alex@Hesperia:~/psp/libvorbis$ make
alex@Hesperia:~/psp/libvorbis$ make install

libTremor

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/libTremor
alex@Hesperia:~/psp$ cd libTremor
alex@Hesperia:~/psp/libTremor$ LDFLAGS="-L$(psp-config --pspsdk-path)/lib -lc -lpspuser" ./autogen.sh --host psp --prefix=$(psp-config --psp-prefix)
alex@Hesperia:~/psp/libTremor$ make
alex@Hesperia:~/psp/libTremor$ make install

10º SDL_mixer

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/SDL_mixer
alex@Hesperia:~/psp$ cd SDL_mixer
alex@Hesperia:~/psp/SDL_mixer$ ./autogen.sh
alex@Hesperia:~/psp/SDL_mixer$ LDFLAGS="-L$(psp-config --pspsdk-path)/lib -lc -lpspuser" ./configure --host psp --with-sdl-prefix=$(psp-config --psp-prefix) --disable-music-mp3 --prefix=$(psp-config --psp-prefix) --disable-music-libmikmod --enable-music-mod
alex@Hesperia:~/psp/SDL_mixer$ make
alex@Hesperia:~/psp/SDL_mixer$ make install

11º freetype

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/freetype
alex@Hesperia:~/psp$ cd freetype
alex@Hesperia:~/psp/freetype$ sh autogen.sh
alex@Hesperia:~/psp/freetype$ LDFLAGS="-L$(psp-config --pspsdk-path)/lib -lc -lpspuser" ./configure --host psp --prefix=$(psp-config --psp-prefix)
alex@Hesperia:~/psp/freetype$ make
alex@Hesperia:~/psp/freetype$ make install

12º SDL_ttf

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/SDL_ttf
alex@Hesperia:~/psp$ cd SDL_ttf
alex@Hesperia:~/psp/SDL_ttf$ ./autogen.sh
alex@Hesperia:~/psp/SDL_ttf$ LDFLAGS="-L$(psp-config --pspsdk-path)/lib -lc -lpspuser" ./configure --host psp --with-sdl-prefix=$(psp-config --psp-prefix) --with-freetype-prefix=$(psp-config --psp-prefix) --without-x --prefix=$(psp-config --psp-prefix)
alex@Hesperia:~/psp/SDL_ttf$ make
alex@Hesperia:~/psp/SDL_ttf$ make install

13º pspgl

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/pspgl
alex@Hesperia:~/psp$ cd pspgl
alex@Hesperia:~/psp/pspgl$ make
alex@Hesperia:~/psp/pspgl$ make install

14º openssl

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/openssl
alex@Hesperia:~/psp$ cd openssl
alex@Hesperia:~/psp/openssl$ wget http://www.openssl.org/source/openssl-0.9.7j.tar.gz
alex@Hesperia:~/psp/openssl$ gunzip < openssl-0.9.7j.tar.gz | tar xv
alex@Hesperia:~/psp/openssl$ cd openssl-0.9.7j/
alex@Hesperia:~/psp/openssl$ patch -p1 < ../openssl-0.9.7j.patch
alex@Hesperia:~/psp/openssl$ ./Configure psp --prefix=$(psp-config --psp-prefix) threads zlib no-shared no-asm
alex@Hesperia:~/psp/openssl$ make
alex@Hesperia:~/psp/openssl$ make install

15º ode

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/ode
alex@Hesperia:~/psp$ cd ode
alex@Hesperia:~/psp/ode$ make
alex@Hesperia:~/psp/ode$ cp include/ode /usr/local/include/ode
alex@Hesperia:~/psp/ode$ cp lib/libode.a /usr/local/lib/libode.a

16º mikmodlib

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/mikmodlib
alex@Hesperia:~/psp$ cd mikmodlib
alex@Hesperia:~/psp/mikmodlib$ make libs
alex@Hesperia:~/psp/mikmodlib$ make install

17º microwindows

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/microwindows
alex@Hesperia:~/psp$ cd microwindows
alex@Hesperia:~/psp/microwindows$ cd src
alex@Hesperia:~/psp/microwindows/src$ make
alex@Hesperia:~/psp/microwindows/src$ make install

18º lua

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/lua
alex@Hesperia:~/psp$ cd lua
alex@Hesperia:~/psp/lua$ make -f Makefile.psp
alex@Hesperia:~/psp/lua$ make -f Makefile.psp install

19º libpthreadlite

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/libpthreadlite
alex@Hesperia:~/psp$ cd libpthreadlite
alex@Hesperia:~/psp/libpthreadlite$ make all
alex@Hesperia:~/psp/libpthreadlite$ make install

20º libmikmod

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/libmikmod
alex@Hesperia:~/psp$ cd libmikmod
alex@Hesperia:~/psp/libmikmod$ make
alex@Hesperia:~/psp/libmikmod$ make install

21º libmad

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/libmad
alex@Hesperia:~/psp$ cd libmad
alex@Hesperia:~/psp/libmad$ make
alex@Hesperia:~/psp/libmad$ make install

22º libbulletml

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/libbulletml
alex@Hesperia:~/psp$ cd libbulletml
alex@Hesperia:~/psp/libbulletml$ cd src
alex@Hesperia:~/psp/libbulletml/src$ make
alex@Hesperia:~/psp/libbulletml/src$ make install

23º jpeg

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/jpeg
alex@Hesperia:~/psp$ cd jpeg
alex@Hesperia:~/psp/jpeg$ make
alex@Hesperia:~/psp/jpeg$ make install

24º cal3D

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/cal3D
alex@Hesperia:~/psp$ cd cal3D
alex@Hesperia:~/psp/cal3D$ LDFLAGS="-L$(psp-config --psp-prefix)/lib -L$(psp-config --pspsdk-path)/lib" LIBS="-lpsplibc -lpspuser" ./configure --host=psp --disable-shared --prefix=$(psp-config --psp-prefix)
alex@Hesperia:~/psp/cal3D$ make
alex@Hesperia:~/psp/cal3D$ make install

25º bzip2

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/bzip2
alex@Hesperia:~/psp$ cd bzip2
alex@Hesperia:~/psp/bzip2$ make
alex@Hesperia:~/psp/bzip2$ make install

26º aalib

Código: Seleccionar todo

alex@Hesperia:~$ cd psp/
alex@Hesperia:~/psp$ svn co svn://svn.ps2dev.org/psp/trunk/aalib
alex@Hesperia:~/psp$ cd aalib
alex@Hesperia:~/psp/aalib$ make
alex@Hesperia:~/psp/aalib$ make install


Como seguramente habréis notado, hay alguna que otra librería que falta. Esto es porque hay algunas que son herramientas (que veremos a continuación), hay otras que son anticuadas y no llegan a ser interesantes en este momento, y hay otras que son de prueba.

De nuevo, estas son las más habituales, su instalación rápida y sólo recomendada cuando sea necesaria.



Herramientas: PRXtool:

Spoiler:
Para este tema de herramientas, usaré por lo general el propio sistema de la PSP, o, en este caso, Windows; por tener un acceso más rápido y orientativo en el tema de las ventanas.

PRXtool es una herramienta que desarrolló TyRaNiD en ps2dev.org y que es, como se suele decir, una navaja multiusos para el tema de ingeniería inversa y de análisis de binarios prx/elf que se usan en el propio sistema de la PSP.

Para su instalación, acudiremos a los siguientes comandos:

Código: Seleccionar todo

svn co svn://svn.ps2dev.org/psp/trunk/prxtool
cd prxtool
./bootstrap
./configure
make
make install

siendo la instalación última opcional, sobretodo para GNU/Linux para poder acceder al comando sin más dilación. Sin embargo, en Windows directamente la compilación con el make nos devolverá el ejecutable .exe que utilizaremos.
prxtool.7z


De igual manera, al ejecutarlo por primera vez, veremos algo como:
12.PNG


Como veis, hay multitud de opciones, y hay muchas, muchas cosas que podemos hacer con ellas. Vamos a verlas, una tras otra. Para poder manejar estas opciones, supondremos que tenemos un archivo PRX desencriptado ctrl.prx, y trabajaremos con él de forma general.

Nota: Si queréis saber cómo hemos conseguido dicho ctrl.prx, acudid a la sección de la herramienta PSARdumper, por ejemplo. Por motivos de legalidad no se incluye en este post.

La estructura básica se define por:

Código: Seleccionar todo

./prxtool [opciones] [archivo]


Output (--output / -o)
Esta opción permite definir un archivo de salida. De esta manera, podemos evitar que el resultado del trabajo que hemos hecho salga por pantalla (stdout), y se vuelque en un archivo.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -o ctrl.txt ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Reloc count 358, .reloc, data 0x0, text 0x0
Done

IDCout (--idcout / -c / default)
Es la salida por defecto que efectúa al ejecutarse sobre un archivo prx/elf. De esta manera, si realizamos lo anterior (con o sin salida por pantalla), nos devolverá un archivo IDC, los usados habitualmente en IDA y C para ingeniería inversa. Ya sea añadiendo la flag -c o sin añadirla, ese será el resultado.

Código: Seleccionar todo

...
  MakeFunction(0x00000120, BADADDR);
}

static createRelocs() {
Reloc count 358, .reloc, data 0x0, text 0x0
}

Done

Alejandro@hesperia ~/prxtool
$

MAPout (--mapout / -a)
De igual manera que en el caso anterior del IDCout, en esta ocasión tenemos la posibilidad de que nos devuelva un archivo MAP como resultado del trabajo del PRXtool (es decir, de la de-compilación), es decir, un archivo en clave ASM que define los NIDs pertinentes de cada función.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -o ctrl.asm -a ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Reloc count 358, .reloc, data 0x0, text 0x0
Done

XMLout (--xmlout / -x)
De nuevo, otro tipo de salida. En este caso, permite definir una salida como archivo XML, es decir, un archivo de tipología web que permite tener una salida estructurada y definida que se suele usar, por ejemplo, para la definición más exacta de nombres de funciones y para posterior desarrollo; como es el caso de los libdoc. Una vez con los nombres de las funciones, esta opción puede permitir devolver un archivo más comprensible.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -o ctrl.xml -x ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Done

ELFout (--elfout / -e)
Esta es la última de las salidas más comunes. En esta ocasión, permite sacar un archivo .ELF desde un .PRX, como decimos. Para más información acerca de estos dos formatos, revisa el apéndice especificado de esa misma manera.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -o ctrl.elf -e ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
size: 328, sectcount: 6, strsize: 36
Done

Debug (--debug / -d)
Esta simple opción permite definir un modo "debug" de comprobación del proceso, mostrado por pantalla. Aunque definamos una salida, esta relación se mostrará de esa manera y nos permitirá ver si ha habido algún error en el proceso. Esta opción es bastante interesante para cuando tenemos que realizar procesos más complicados que vemos más adelante.

Código: Seleccionar todo

...
Debug: Hi at (000016C4) 261
Debug: Matching low at 262
Debug: Finished at 262
Debug: Invalid memory address 0x00009DB0
Reloc count 358, .reloc, data 0x0, text 0x0
Done

Alejandro@hesperia ~/prxtool
$

Serial (--serial ixrsl / -s ixrsl)
El modo "serial" permite definir qué se quiere imprimir (por defecto en stdout, nosotros siempre en output). Podemos distinguir entre Imports, Exports, Relocs, Sections, SyslibExp. Es decir, segmentos, información del módulo, exports/imports, etcétera.

Código: Seleccionar todo

...
Alejandro@hesperia ~/prxtool
$ ./prxtool -s l -o ctrl.txt ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Done

Alejandro@hesperia ~/prxtool
$ ./prxtool -s ixrsl -o ctrl.txt ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Reloc count 358, .reloc, data 0x0, text 0x0
Done

XMLfile (--xmlfile ex.xml / -n ex.xml)
Permite indicar un archivo .XML que tenemos de por sí para usarlo en las opciones de decompilación. Esta opción es muy interesante, ya que podemos usar fácilmente un archivo libdoc (básicamente un XML con las funciones y NIDS descritos) como los que podríamos haber hecho anteriormente con la opción -x, y usarlo para que directamente nos devuelva un archivo más comprensible. Siempre podeis recuperar los libdoc y mucha información acerca de los NIDs descubiertos en esta página.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -n 352_psplibdoc_201008.xml -o ctrl.txt ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Reloc count 358, .reloc, data 0x0, text 0x0
Done

XMLdis (--xmldis / -g)
Esta opción nos permite habilitar el modo de "dissassembling" a la hora de usar un archivo XML, como veíamos anteriormente. Ante esto, poco más hay que explicar.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -n 352_psplibdoc_201008.xml -g -o ctrl.txt ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Reloc count 358, .reloc, data 0x0, text 0x0
Done

10º XMLdb (--xmldb titulo / -w titulo)
Esta opción nos permite devolver el proceso del archivo como una base de datos XML definida en lenguaje ASM con un título (que podemos obviar) de encabezamiento ELF.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -w -o ctrl.asm ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Done

11º Stubs (--stubs / -t)
Permite devolver los "stubs", es decir los .S de cada función / nombre del archivo XML seleccionado anteriormente.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -t 352_psplibdoc_201008.xml
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Done

12º PRXStubs (--prxstubs / -u)
De igual manera que la anterior, devuelve los stubs para un archivo .prx definido con anterioridad. La diferencia redundante entre esta opción y la anterior es que ésta se restringe sólo a la "familia" de funciones de dicho prx, mientras que los XML suelen recuperar todos los stubs de todas las familias incluídas.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -u ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loaded PRX ctrl.prx successfully
Dependancy list for ctrl.prx
Done

13º NewStubs (--newstubs / -k)
Esta opción, en contraprestación a la de los stubs normales, permite hacer el mismo trabajo pero con la estructura más actual que se define en el SDK.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -k -o ctrl.txt ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Reloc count 358, .reloc, data 0x0, text 0x0
Done

14º Depends (--depends / -q)
Esta opción permite imprimir las dependencias de los PRX que utilicemos, con la opción de poder añadir un archivo .XML al proceso.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -n 352_psplibdoc_201008.xml -q ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loaded PRX ctrl.prx successfully
Dependancy list for ctrl.prx
Dependancy 0 for SysMemForKernel: sysmem.prx
Dependancy 1 for sceSuspendForKernel: sysmem.prx
Dependancy 2 for sceSysEventForKernel: sysmem.prx
Dependancy 3 for InterruptManagerForKernel: interruptman.prx
Dependancy 4 for SysclibForKernel: sysmem.prx
Dependancy 5 for ThreadManForKernel: threadman.prx
Dependancy 6 for SysTimerForKernel: systimer.prx
Dependancy 7 for sceDisplay_driver: display.prx
Dependancy 8 for sceSyscon_driver: syscon.prx
Done

15º ModInfo (--modinfo / -m)
Habilita el modo de información, imprimiendo la información referente al módulo o librería, como es el caso de nombres, funciones, imports, variables, flags, etcétera.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -m ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loaded PRX ctrl.prx successfully
Module information

Name:    sceController_Service
Attrib:  1007
Version: 1.6
GP:      00008040

Exports:
Export 0, Name syslib, Functions 2, Variables 2, flags 80000000
Export 1, Name sceCtrl, Functions 16, Variables 0, flags 40010011
Export 2, Name sceCtrl_driver, Functions 27, Variables 0, flags 00010011

Imports:
Import 0, Name SysMemForKernel, Functions 1, Variables 0, flags 00010011
Import 1, Name sceSuspendForKernel, Functions 1, Variables 0, flags 00010011
Import 2, Name sceSysEventForKernel, Functions 2, Variables 0, flags 00010011
Import 3, Name InterruptManagerForKernel, Functions 6, Variables 0, flags 00090011
Import 4, Name SysclibForKernel, Functions 1, Variables 0, flags 00010011
Import 5, Name ThreadManForKernel, Functions 7, Variables 0, flags 00010011
Import 6, Name SysTimerForKernel, Functions 6, Variables 0, flags 00010011
Import 7, Name sceDisplay_driver, Functions 1, Variables 0, flags 00010011
Import 8, Name sceSyscon_driver, Functions 2, Variables 0, flags 00010011
Done

16º ImpExp (--impexp / -f)
De igual manera que la anterior, pero imprimiendo tan sólo los imports/exports. Aquí podemos añadir, de nuevo, un archivo XML con NIDS definidas para poder tener un resultado más afable.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -n 352_psplibdoc_201008.xml -f ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loaded PRX ctrl.prx successfully
Module information

Name:    sceController_Service
Attrib:  1007
Version: 1.6
GP:      00008040
...
0x3AC3D2A4 [0x000018F4] - sceSysconCmdExecAsync
0x9E6E060F [0x000018FC] - sceSyscon_driver_9E6E060F
Done

17º Disasm (--disasm / -w)
Permite habilitar el modo de disassembling. Es decir, procura ingeniería inversa a un archivo PRX/ELF devolviendo un resultado en ASM como veíamos en la opción -a.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -w -o ctrl.dis ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Done

18º Disopts (--disopts xdrsmw / -i xdrsmw)
Esta opción, junto con la anterior, permite definir una serie de opciones para el proceso de disassembling. De esta manera, si añadimos "x", nos devolverá la información en forma hexadecimal, si añadimos "xd" será en forma de hexadecimal pero con firma, si añadimos "r" tendremos un formato rN en vez de los habituales mnemonics, si añadimos "s" imprimirá automáticamente el PC que usemos como símbolo, si añadimos "m" deshabilitaremos las instrucciones macro, y si añadimos "w" podremos indicar los opcodes necesarios tras el proceso.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -w -i xdrw -o ctrl.dis ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Done

19º Binary (--binary / -b)
Al ser usado con la opción disasm -w, permite definir al archivo que se trata como un binario.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -w -b -i xdrw -o ctrl.dis ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Done

20º Database (--database [offset] / -l [offset])
De nuevo, otra de las opciones para -w. Con ella, podemos definir el offset que queremos utilizar para el archivo en cuestión.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -w -l 0x80 -i xdrw -o ctrl.dis ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Done

21º Reloc (--reloc [dirección] / -r [dirección])
Esta opción, relativamente poco usada, permite hacer una recolocalización del archivo PRX con el que estamos trabajando a otra dirección.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -r 0x80 -o ctrl.txt ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Reloc count 358, .reloc, data 0x0, text 0x0
Done

22º Symbols (--symbols / -y)
Una de las opciones de salida que se quedaron atrás. Permite definir una salida simbólica (en el caso de que estén disponibles en el PRX/ELF)

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -y ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loading ctrl.prx
Loaded PRX ctrl.prx successfully
Error: No symbols available
Done

23º Funcs (--funcs [archivo] / -z [archivo])
Esta opción permite definir un archivo que se use conjuntamente con y para el disassembling. Sin embargo, y ya que podemos hacer lo mismo pero con un archivo XML, es de poco interés, de manera que pasaré por encima solo.

24º Alias (--alias / -A)
Esta última opción nos permite imprimir los alias de las funciones al imprimir los imports/exports de cada uno. De nuevo, sólo en pantalla.

Código: Seleccionar todo

Alejandro@hesperia ~/prxtool
$ ./prxtool -f -A -o ctrl.txt ctrl.prx
PRXTool v1.1 : (c) TyRaNiD 2k6
Built: May 31 2010 17:17:08
Loaded PRX ctrl.prx successfully
Module information

Name:    sceController_Service
Attrib:  1007
Version: 1.6
GP:      00008040
...
0x3AC3D2A4 [0x000018F4] - sceSyscon_driver_3AC3D2A4
0x9E6E060F [0x000018FC] - sceSyscon_driver_9E6E060F
Done



Herramientas: PSARdumper:

Spoiler:
El PSARdumper es una herramienta más conocida, casi por la cantidad de mods y noticias que se han creado relacionadas desde la existencia de los primeros, originalmente por PspPet en este hilo de ps2dev.org, y con las consiguientes modificaciones que se han ido realizando.

Básicamente es una herramienta que permite descomprimir el EBOOT.PBP de actualizaciones de Firmware para sacar el archivo base, el DATA.PSAR que incluye la información relevante a estas actualizaciones, y con ello los archivos que luego se verán distribuidos por las particiones de la NAND flash.

De un proceso más engorroso y largo, acabó siendo algo muy simple, y realmente interesante cuando se quiere desencriptar los archivos pertinentes. Claro que, para ello hacen falta las claves de cifrado de cada firmware que, por lo general, suelen ser diferentes siempre.

Ha habido multitud de revisiones de esta herramienta, a medida que iban saliendo nuevos modelos (tanto revisiones de software como de hardware), de manera que la escena es variopinta. Sin embargo, se podría decir que el último a esta fecha (que incorpora todas las revisiones anteriores) es uno actualizado por bbtgp incluyendo las claves para los firmwares 6.00 a 6.20, aunque hace poco ha salido uno nuevo, en el cual se incluyen partes de las claves de archivos 05g (es decir, de la PSPGo) por parte de coyotebean.

A pesar de ello, no está completo, y es por ello que aquí incluyo la descarga de estas dos anteriores.
PSARDUMPER_6XX.zip

newpsardump_pspgo.zip


Para su instalación, se incluyen en nuestra carpeta ms0:/PSP/GAME/ dejando como es obvio la carpeta /src/ sin meter pues son las sources originales; y el EBOOT.PBP que se quiera usar, en la propia raíz de la MS, ms0:/.

Si lo ejecutamos en nuestra PSP desde PSP - Juegos, veremos esta imágen:
13.PNG

a parte de las contribuciones (de las que, siendo totalmente sincero, algunas faltan), tenemos tres opciones distintas:

:equis: para dumpear los archivos del PSAR _con_ la firma y desencriptando el reboot.bin

:circulo: para dumpear los archivos del PSAR _sin_ la firma y sin desencriptar el reboot.bin

:cuadrado: para la opción más habitual, desencriptar todo.

Al final, el resultado acabará en una carpeta llamada F0 (en honor a la flash0) dentro de la raíz de nuestra MS, ms0:/F0/.



Herramientas: PSPLinkUSB:

Spoiler:
Esta herramienta es otra de las más conocidas y sin embargo, menos utilizadas. Siendo lo efectiva que es, como depuradora de programas y como otra de esas navajas suizas de todo en uno, es muy raro que tan poca gente llegue a utilizarlo de hecho.

Personalmente, el uso que le doy es para la búsqueda de vulnerabilidades, lo que es lo mismo que, hablando en una jerga que seguramente conozcais más, la búsqueda de exploits. (Descartando crashes que no sirven de nada)

Para ello, esta herramienta es esencial. A la vez que, como se ha comentado, para la depuración. Sin embargo, son necesarios ciertos conocimientos de MIPS ASM para las tareas más avanzadas, así como un conocimiento general acerca de dónde nos estamos metiendo.

Por lo general, se puede trabajar bajo Windows o bajo Linux. De cualquiera de las maneras, la compilación es la misma:

Código: Seleccionar todo

svn co svn://svn.ps2dev.org/psp/trunk/psplinkusb
cd psplinkusb
make release
cd release_oe/pc/pspsh/
make
cd ../usbhostfs_pc/
make


O bien, descargad la versión adecuada de los siguientes links:
psplinkusb_Linux.7z

psplinkwin.7z


El proceso de compilación descrito anteriormente nos permitirá crear una serie de ejecutables, que podemos encontrar en ambas descargas anteriores. Por lo general, es siempre interesante dejar dichos ejecutables en un lugar accesible, como puede ser en C:\ en Windows y en /usr/bin/ en GNU/Linux.

Como veis, de cualquier manera, a parte de la carpeta release_oe/, tenemos otra que es /release/, que podríamos haber hecho el mismo proceso en para conseguir unos ejecutables que sirvan para los firmwares 1.0/1.5; aunque es en esta primera, /release_oe/, donde tenemos la versión adaptada a los CFW que son más habituales hoy en día.

Pues bien, podemos ejecutarlo de dos formas distintas, ya sea por un EBOOT o bien por un PRX. El proceso, independientemente de la elección es el mismo, de manera que veamos las distintas ramificaciones.

Si queremos ejecutarlo como un EBOOT, entonces tendremos que copiar el EBOOT.PBP que se encuentra en /release_oe/psplink/ o bien en la descarga anterior directamente a ms0:/PSP/GAME/psplink/ y ejecutarlo.

Si queremos ejecutarlo como un PRX (recomendado), entonces tendremos que asignar el archivo /release_oe/psplink/psplink.prx y /release_oe/psplink/usbhostfs.prx como plugin dentro de ms0:/seplugins/ y activándolos tanto en VSH como en GAME añadiendo las siguientes líneas a vuestros archivos ms0:/seplugins/vsh.txt y ms0:/seplugins/game.txt:

Código: Seleccionar todo

ms0:/seplugins/usbhostfs.prx 1
ms0:/seplugins/psplink.prx 1

y confirmando que están activados directamente en el Modo Recovery de vuestra PSP.

Una vez llegado a ese punto, el hecho será el mismo tanto si trabajamos con un EBOOT como con un PRX dentro de /seplugins/, de manera que ambas ramificaciones se unen a partir de ahora. Supondremos que tenemos permisos de administrador/root, dependiendo del caso para Windows o GNU/Linux. Sin embargo, seguiremos el caso de instalación por plugin, ya que a posteriori será más efectiva; y siempre sin que esté montado el USB para empezar.

Con la PSP apagada y los plugins activados, la conectamos vía USB y la encendemos. Nos la detectará de nuevo como type "B", y en ese instante nos pedirá los drivers. En el caso de Windows, tendremos que especificarles los que vayamos a usar, ya sean de 32 o 64 bits, como se indican en la descarga o en /release_oe/pc/windows/driver*

Desde Windows: Abrimos dos cmd's y ejecutamos en primer lugar el usbhostfs_pc;

Código: Seleccionar todo

C:\psplinkwin>usbhostfs_pc.exe
USBHostFS (c) TyRaNiD 2k6
Built Jun  2 2010 11:56:19 - $Revision: 2368 $
Connected to device

y otro en el que ejecutemos nuestro pspsh;

Código: Seleccionar todo

C:\psplinkwin>pspsh.exe
host0:/>

apareciendo lo siguiente en el otro cmd:

Código: Seleccionar todo

C:\psplinkwin>usbhostfs_pc.exe
USBHostFS (c) TyRaNiD 2k6
Built Jun  2 2010 11:56:19 - $Revision: 2368 $
Connected to device
Accepting async connection (0) from 127.0.0.1
Accepting async connection (2) from 127.0.0.1
Accepting async connection (3) from 127.0.0.1

Y listo. Ya tenemos nuestro psplinkusb preparado para matar.

Desde GNU/Linux, en mi caso Ubuntu 10.04, en una misma terminal abrimos dos pestañas, y en una ejecutamos nuestro usbhostfs_pc en root,

Código: Seleccionar todo

alex@Hesperia:~$ su
Contraseña:
root@Hesperia:/home/alex# usbhostfs_pc
USBHostFS (c) TyRaNiD 2k6
Built Jun  2 2010 12:40:21 - $Revision: 2368 $
Connected to device

y en la otra pestaña ejecutamos nuestro pspsh,

Código: Seleccionar todo

alex@Hesperia:~$ pspsh 
host0:/>

apareciendo, de nuevo, lo siguiente en la primera pestaña:

Código: Seleccionar todo

root@Hesperia:/home/alex# usbhostfs_pc 
USBHostFS (c) TyRaNiD 2k6
Built Jun  2 2010 12:40:21 - $Revision: 2368 $
Connected to device
Accepting async connection (0) from 127.0.0.1
Accepting async connection (2) from 127.0.0.1
Accepting async connection (3) from 127.0.0.1

Y listo. Ya tenemos de nuevo nuestro psplinkusb listo para matar... y con más eficacia, siendo en Linux.

Ahora bien, el proceso de "debugging" o como querais llamarlo es más complicado que todo esto. Por un lado, y ya que tenemos activado el plugin tanto en nuestro VSH como en GAME, esto implica que podremos monitorizar la actividad que se haga via USB de nuestra PSP y analizar los crashes por medio de estas terminales.

De esta manera, cuando haya algún error o simplemente cuando se llame a alguna función desde nuestro programa, esta función y/o errores se mostrarán en el host0 de nuestro pspsh, mientras que el usbhost recuperará las conexiones entrantes y/o salientes.

De igual manera, podemos ejecutar cualquier programa que tengamos dentro de nuestra PSP, por ejemplo:

Código: Seleccionar todo

host0:/> cd ms0:/PSP/GAME/app/
ms0:/PSP/GAME/app/>./EBOOT.PBP

así como con archivos PRX/ELF y otras rutas, no necesariamente un ms0.

Considerad a esa shell del psplinkusb como una propia terminal de GNU/Linux, con acceso directo a vuestra PSP. Por lo tanto, podreis siempre ejecutar y monitorizar lo que suceda, como ya he comentado; y podreis utilizar los comandos más habituales (que, a parte de los usuales, una buena lista se explica con el comando "help" en nuestro host0 del pspsh.

De igual manera que accedimos a ms0 podemos acceder a flash0, de manera que es bastante sencillo cargar directamente el VSH mediante su vshmain.prx, o mediante un reset.

A partir de aquí, cada uno es libre de seguir el camino que le sea más favorable. Personalmente, considero que una de las mejores pruebas con el psplinkusb es realizar nuestros propios programas y ver cómo lo interpreta, con el código al lado, y darnos cuenta de nuestros errores antes de que sean "fatales".



Herramientas: NIDattack:

Spoiler:
Como comentamos hace un tiempo al hablar de NIDs, existe una página mantenida por SilverSpring y anteriormente por moonlight (aka Dark_AleX) en la cual podemos encontrar un gran número de funciones, NIDs y libdocs, que al fin y al cabo es la base de toda nuestra programación.

Pero, ¿de dónde viene todo esto? ¿De dónde sacamos esas NIDs y nombres de funciones si se supone que son oficiales? NIDattack es la respuesta.

Básicamente, es un programa creado por djhuevo de bruteforcing que permite, mediante un algoritmo, descifrar los nombres de las funciones partiendo de un NID, sea cual sea. Para tal efecto, sin embargo, necesita de un diccionario y de otras cuestiones que veremos a continuación.

A pesar de que podemos bajar la versión "oficial" del NIDattack de la siguiente manera y compilarla:

Código: Seleccionar todo

svn co svn://svn.ps2dev.org/psp/trunk/nidattack
cd nidattack/src
make

es una versión bastante antigua.

Para ello, y devolviendo el antiguo esplendor al hilo original donde se creó, utilizaremos la versión 5.4 que podeis bajar del siguiente enlace, ya compilada con la source.
nidattack.7z


Al ejecutarlo, podremos ver lo siguiente:

Código: Seleccionar todo

Alejandro@hesperia ~/nidattack
$ ./nid.exe
SHA1 hash dictionary attack v5.4 by adresd
based on the original by djhuevo

Running SHA1 Check : 'MyTestString'(12)  - Sanity Check Passed
Running SHA1 Check : 'abc'(3)  - Sanity Check Passed
Running SHA1 Check : 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopn'(53)
  - Sanity Check Passed

usage:
        ./nid <hash_list> <dictionaryfirst> <dictionarymain> [prefix]


De manera que, para su correcto funcionamiento, necesitaremos de:
- Nuestro NIDattack.
- Una lista de hashes.
- Un primer diccionario.
- Un segundo diccionario.
- Una lista de prefijos.
sin embargo, no todo es necesario.

Como recordamos de esa página de la que hemos hablado anteriormente, podemos obtener lo segundo de nuestra lista, los hashes necesarios. ¿Que qué son estos?

Supongamos que queremos intentar crackear las funciones de sceImpose_Driver para 3.5x que podemos ver aquí. Como vemos, tenemos una lista de nombres de funciones junto con una lista de números 0xABCDEF01. Esos son los que llamaremos como hashes.

Por lo tanto, si queremos intentar con esta librería, tendremos que crear un archivo de texto, por ejemplo, hash.txt en el que añadiremos lo siguiente:

Código: Seleccionar todo

0x9BA61B49
0xA9884B00
0xBB3F5DEC
0xE0887BC8
0xFCD44963
0xFF1A2F07
0x7084E72C
0x9DBCE0C4

uno por línea, de cada una de las funciones que aún no están descubiertas.

Estos hashes se pueden obtener o bien desde el PRXtool con nuestra herramienta de stubs, o bien mediante un análisis más detallado en un IDA, por poner un ejemplo.

Ahora bien, lo siguiente que _necesitamos_ es un diccionario, al menos uno. En la estructura anterior se define como si se necesitasen dos diccionarios mínimo, pero eso es porque el primer diccionario es el que indica las primeras palabras de la función.

Por lo tanto, podemos o bien usar este primer diccionario o bien usar el prefijo que se incluye al final. Supongamos el primer caso, y creemos un archivo de texto llamado dicf.txt en el que incluímos:

Código: Seleccionar todo

sceImpose

pues así es como comenzarán todas las funciones posibles.

Claro que, nos queda lo principal, el diccionario dic.txt bajo el cual se hará el proceso de bruteforcing. Este diccionario habrá de incluir las palabras que puedan estar dentro de la función, como nombres posibles. Por lo tanto, podría ser algo como...

Código: Seleccionar todo

A
Ata
Set
Check
Language
Mode
Home
Param
...

en orden alfabético y sin olvidarnos de incluir las letras del alfabeto (jugando con minúsculas y mayúsculas) así como carácteres especiales.

Pero claro, ¿de dónde podríamos sacar las palabras posibles? Lo más sencillo es, sin duda alguna, de lo que ya sabemos. Por lo tanto, podemos ir directamente a las funciones que ya conocemos e ir diferenciando palabra por palabra, una por línea, en nuestro dic.txt, hasta tener muchas, pero muchas de verdad.

Recordad, sin embargo, que cuanto más largo sea el diccionario, mayor será el tiempo necesario para ejecutarlo. Una vez hecho, por lo tanto, tendremos que hacer algo como:

Código: Seleccionar todo

./nid hash.txt dicf.txt dic.txt

cambiando cada diccionario para cada bruteforcing que se haga; y cada vez ampliando más y más nuestro diccionario principal.

Una vez que haya terminado, con suerte habremos conseguido algún resultado, y con más suerte aún será algún resultado fiable. Pues lo más habitual en estos casos es conseguir un falso positivo, con nombres que suelen ser más que hilarantes.

Sin embargo, de nuevo, para poder comprobar que esa función es correcta, se ha de analizar via algún debugger o mediante el mismo IDA para poder analizar sus variables y todo su conjunto. El hecho de descubrir algo medianamente posible no implica ni mucho menos que se haya terminado el trabajo.



Herramientas: PRXdecrypter:

Spoiler:
Aunque esta herramienta no es ni mucho menos tan conocida como podría ser cualquier otra, es más que digna de mención, tanto por el tiempo que lleva desarrollándose, como por sus actualizaciones y por la calidad de la misma.

Creada por jas0nuk, básicamente es un programa que se utiliza bajo la PSP que permite, de forma parecida al PSARdumper, desencriptar archivos PRX y con ello módulos oficiales y no oficiales, así como descifrar las compresiones habituales.

Del readme, podemos ver la siguiente lista de funciones que permite realizar este programa:
readme escribió:Puede desencriptar/descomprimir/extraer:
* Módulos de los firmwares oficiales hasta 6.20.
* Módulos de las actualizaciones oficiales, incluso las ofuscadas.
* El propio DATA.PSP de las actualizaciones.
* Archivos reboot.bin y reboot_02g.bin de todos los firmwares.
* Archivos de juegos como el EBOOT.BIN y algún que otro archivo de debug.
* Módulos de los firmwares no oficiales de M33.
* Archivos con compresiones RLZ/KL3E/KL4E.
* meimg.img y me_sdmig.img.
* Archivos relacionados con el DATA.PSP y de demos.
* index.dat.
* Archivo 1SEG.PBP.


Es decir, de nuevo, otra navaja suiza con la que poder descifrar prácticamente todo lo que llegue a nuestras manos, y más aún con esta nueva actualización (2.4b) que ha salido hace relativamente poco tiempo, y que podeis descargar a continuación.
PRXdecrypter.7z


Para su uso, a parte de meter la carpeta PRXdecrypter en ms0:/PSP/GAME, creamos una carpeta llamada "enc" en la raíz de la ms0, tal que meteremos en ms0:/enc/ los archivos cifrados y/o comprimidos con los que queramos trabajar. De igual manera, y aunque es opcional es interesante, crearemos otra que sea ms0:/dec/

Al ejecutar el programa desde Juegos - Memory Stick, podremos ver esta imágen:
14.PNG

y, como vemos, tenemos distintas funciones, que las vamos a ver.

- Decrypt/decompress files es el proceso más habitual. Al pulsar :equis: sobre él, descifrará y/o descomprimirá los archivos que se encuentren en nuestra carpeta enc.

- Analyze files nos permite analizar los archivos que hemos metido en nuestra carpeta enc, sin cambiarlos anteriormente. Esto es bastante interesante para conocer de por sí si los archivos que hemos añadido tienen una compresión en especial o ya hemos trabajado con ellos anteriormente, así como para confirmar el primer paso.

- Signcheck files / Unsigncheck files nos permitirán, como su propio nombre indican, a quitar la firma de los archivos (para que sean compatibles con cualquier PSP) y a poner la firma única de nuestra PSP a esos archivos (para poder, por ejemplo, restaurar un archivo de flash0:/kd/ que necesitemos, pero que era de otra máquina).

- Switch output folder between ms0:/enc/ and ms0:/dec/ es una de las opciones más interesantes y que tendreis que, bajo mi juicio, usar siempre, ya que permite que los archivos resultantes se guarden en la carpeta /dec/ que creamos anteriormente, con tal de que no se sobreescriban a los originales de /enc/. Un paso opcional, pero como digo, necesario para mi juicio.

- Extract reboot.bin/reboot_02g.bin nos permitirá, como su nombre indica, sacar los homónimos archivos de los loadexec.prx [reboot.bin para loadexec.prx < 3.60 (que habrá de ser renombrado a loadexec_reboot.prx) y reboot_02g.bin para loadexec.prx >= 3.60 (que habrá de ser renombrado con anterioridad a loadexec_reboot_02g.prx)]

De igual manera, y como comentábamos en el propio readme, hay la posibilidad de desencriptar otro tipo de archivos, como el 1SEG.PBP, DATA.PSP, etcétera. Para su proceso, habría de ser el mismo, meterlo en nuestra carpeta /enc/ y ejecutar el primer paso.

En resumen, una herramienta que cada vez se está convirtiendo en más esencial, y que, más allá de que jas0nuk sepa más que de sobra lo que hace, es otra opción que se ha de tener en cuenta, a la hora de trabajar con toda esta programación.



Estructura Básica: main.c y Makefile:

Spoiler:
Pasemos a algo más práctico.

Es más que habitual el ver que para iniciarse en un lenguaje de programación o en un sistema definido, lo primero de todo es crear un Hello World y supuestamente tras eso todo es un camino de rosas. Pero no es así.

Sin embargo, nunca está de más (y desde luego es algo necesario) el analizar la estructura general que tendremos en nuestros programas, así como en los Makefiles. A pesar de ello, hay innumerables modificaciones que iremos viendo con el paso del tiempo.

De igual manera, tened en cuenta que estamos programando en C, de manera que no me voy a poner a explicar cómo se hace un array o cualquier cosa que se supone que ya deberíais saber.

Código: Seleccionar todo

/* Directivas del pre-procesador. Ya sean propias del directorio del PSPSDK entre <> o de nuestro directorio de compilación entre comillas, las veremos una por una. */
#include <ejemplo1.h>
#include “ejemplo2.h”

// Determinantes del módulo. Ojo, no todas son explícitamente necesarias.
/* PSP_MODULE_INFO indica la información básica del programa. En este sentido, incluimos el Nombre del programa entre comillas (lo que sea), el modo de compilación, ya sea Kernel (0x1000), User (0), o Vsh (No os preocupeis, veremos todo esto), asi como la versión principal y la subversion (es decir, por ejemplo 2 y 5 para la v2.5) */
PSP_MODULE_INFO(“Nombre de nuestro programa”, Modo, Version, Subversion);
/* El PSP_MAIN_THREAD_ATTR nos indica de igual manera en el modo en el que estamos programando, ya sea Kernel (0x0000 o 0), User (PSP_THREAD_ATTR_USER) o Vfpu (THREAD_ATTR_VFPU) */
PSP_MAIN_THREAD_ATTR(Modo);
/* El PSP_NO_CREATE_MAIN_THREAD indica si hay o no que crear un thread principal, claro que esto se puede modificar con otros como PSP_MAIN_THREAD_PRIORITY para indicar la prioridad, PSP_MAIN_THREAD_STACK_SIZE_KB para indicar el tamaño del stack, entre otros.*/
PSP_NO_CREATE_MAIN_THREAD();
/* El PSP_HEAP_SIZE_KB permite indicar el total de memoria en tamaño permisible para el malloc. También se podría usar el PSP_HEAP_SIZE_MAX(); para conseguir el máximo posible. Para los PRX, el tamaño por defecto es de 64kb.*/
PSP_HEAP_SIZE_KB(Tamaño);

// Defines. Para simplificarnos la vida.
#define aaaaaaaa bbbbbbbbb
#define cccccccccc ddddddddd

// Funciones. Es decir, el grueso del programa, con la definición de nuestras variables, voids, y el propio main. Ya sabeis cómo va esto. Lo que no sabeis es lo que meter dentro, que es lo que veremos a continuación.
(…)

// Salida del programa, y a casa. Como todos tenemos mono, veamos una función que veremos hasta la saciedad, para salir del programa, y que se unirá a nuestra conocida función return.
sceKernelExitGame();


Y, por su lado, un Makefile general tendrá las siguientes entradas:

* TARGET = Este es el nombre propio del programa que estamos creando. De esta manera, podríamos tener, por ejemplo, TARGET = programa1
* OBJS = Objetos a compilar. De forma general, como ya sabreis, cuando se compila, también se linkea, transformando los objetos en ejecutables (en nuestro caso PBP, PRX, etc). Teniendo esto en cuenta, podemos tener, por ejemplo, OBJS = main.o graficos.o fuentes.o (transformando nuestros .c en .o para luego ser linkeados) Es decir, los archivos binarios que se generarán en esta compilación.
* INCDIR = Directorios a incluir. A la hora de programar, suele ser necesario incluir ciertos archivos que se tengan en cuenta en la compilación, o simplemente que han de ser incluidos para los procesos posteriores. En este sentido, por ejemplo, INCDIR = $(PSPSDK)/../include/freetype2
* CFLAGS = Flags, o determinantes de la compilación. Esto es prácticamente calcado a la programación en C. Son éstos los que, por ejemplo, nos indican la compresión que ha de tener el ejecutable compilado, o los niveles de optimización -O1 a -O3
* CXXFLAGS = Flags adicionales determinadas de igual manera que la anterior, pero en este caso, son para C++. De forma general, se incluyen las anteriores con un $(CFLAGS) más las nuevas. Entre otras, podemos encontrar -fno-exceptions,
-fno-rtti, -fno-pic, entre otros.
* ASFLAGS = Flags adicionales, extras. Se suele añadir un $(CFLAGS) más las que sean.
* LIBDIR = Directorio de librerías a incluir en la compilación, en el caso de que existan. Por ejemplo, podríamos tener LIBDIR = ./ (si se encuentran en la misma carpeta de compilación)
* LIBS = Librerías a incluir para su compilación. Este apartado es esencial y de lo que más se usará, y donde se incluirán esos flags que llamábamos de “inclusión en el makefile” en los puntos anteriores. Claro que, existen más de los que vimos, teniendo en cuenta los módulos oficiales del sistema. Por ejemplo, podríamos tener LIBS = -lpsppower
* LDFLAGS = Flags adicionales, determinadas por el linker. Entre otras, podemos encontrar a -mno-crt0, -nostartfiles, etcétera.

* PSP_EBOOT_TITLE = Título del Eboot, lo que aparecerá bajo el XMB una vez compilado y vayamos a ejecutarlo. De esta manera, por ejemplo, podríamos tener PSP_EBOOT_TITLE = Mi Primer Programa v1.0
* EXTRA_TARGETS = Como su propio nombre indica, determinantes extras a tener en cuenta para la compilación. Podemos tener, por ejemplo, EXTRA_TARGETS = EBOOT.PBP
* BUILD_PRX = Indicador que permite indicar que estamos compilando un prx. Para que sea efectivo, ha de ser igual a 1.
* PSP_FW_VERSION = Poco útil pero al fin y al cabo otra opción, permite indicar el firmware al que está destinado el programa. Se solía usar sobretodo al portar aplicaciones de 1.5 a 3.x

Y luego, hay un par de líneas que son obligatorias, que se han de incluir al final de todo Makefile a la
hora de programar en PSP, y son las siguientes;

Código: Seleccionar todo

PSPSDK=$(shell psp-config –pspsdk-path)
include $(PSPSDK)/lib/build.mak


A pesar de todo esto, esta estructura general sólo es una aproximación, y tanto en lo que respecta a los Makefiles de forma general como a lo de nuestro sistema en particular, hay y habrá modificaciones. Tenedlo en cuenta simplemente como un vistazo rápido, como una ayuda y revisión muy inicial.



Librerías Oficiales: pspDebug y pspDisplay:

Spoiler:
Como digo, antes de ver un Hola Mundo de por sí, hay que profundizar un poco más. Para ello, tendremos que ver nuestros dos primeros módulos o librerías, conocidas como pspDebug y pspDisplay. Estas dos las veremos juntas por la particular relación que tienen en un punto de vista práctico.

El pspDebug, lo podríamos definir como una directiva que se suele usar para la muestra y devolución de datos en pantalla, así como depuración de errores. (de ahí su nombre debug). Mientras tanto, podríamos definir al pspDisplay por su lado como una directiva que nos ayudará a definir las disposiciones de pantalla, sobretodo en cuanto a respuesta y forma de actuación de la misma.

Nota: A pesar de que en este manual he tratado de analizar todas las funciones posibles, definitivamente no están todas, y hay más de una que falta. Por lo tanto, consideradlo como un W-I-P, ya que dudo que nada de esto llegue a terminarse algún día, considerando el secretismo que existe bajo este desarrollo no-oficial.

Veamos uno por uno. En primer lugar, el pspDebug, que para su uso necesitaremos de esta inclusión como directiva del pre-procesador:

Código: Seleccionar todo

#include <pspdebug.h>

y estas son sus funciones.

Código: Seleccionar todo

void pspDebugScreenInit(void);
/* Esta función permite iniciar la pantalla, de manera que sea ésta la que usemos cuando queramos que nuestros datos, imágenes, texto, etcétera, aparezca en ella. Es una función imperativa para el funcionamiento de la misma.
Ejemplo: pspDebugScreenInit(); */

Código: Seleccionar todo

void pspDebugScreenInitEx(void* vram_base, int mode, int setup);
/* Esta función, al igual que la otra, permite iniciar la pantalla, pero con algunas consideraciones más profundas:
@parámetro vram_base – Dirección base del buffer, si es NULO (vram = NULL;), pues pondrá el valor por defecto.
@parámetro mode – Modo de color. Aquí, podemos tener:
PSP_DISPLAY_PIXEL_FORMAT_565,
PSP_DISPLAY_PIXEL_FORMAT_5551,
PSP_DISPLAY_PIXEL_FORMAT_4444,
PSP_DISPLAY_PIXEL_FORMAT_8888,
es decir, modificaciones de RGB(A) de 16 bits habitualmente. Si mode es 0, tomará por defecto el valor de PSP_DISPLAY_PIXEL_FORMAT_8888
@parámetro setup – Si es 1, permite hacer un setup de la pantalla. Con esto se refiere a lo contenido en src_printf.c, desde donde ajusta varios parámetros de la misma:
#define PSP_SCREEN_WIDTH 480
#define PSP_SCREEN_HEIGHT 272
#define PSP_LINE_SIZE 512
es decir, el tamaño de pantalla y de línea a ser mostrado. Si es 0, toma los valores por defecto (es decir, los definidos anteriormente, usando toda la pantalla)
Ejemplo:
void *vram = NULL;
// o bien por ejemplo void *vram = 0x44000000
pspDebugScreenInitEx(vram, 0, 0); */

Código: Seleccionar todo

void pspDebugScreenPrintf(const char* fmt, argumentos);
/* Esta función es la que nos permite lo que tanto nos gusta, el imprimir texto en pantalla.
@parámetro fmt – Cadena de texto a imprimir, entre comillas.
@argumentos – Argumentos extras para, por ejemplo, definir algo dentro de esa cadena.
Ejemplo: pspDebugScreenPrintf(“Hola, Mundo\!\n”); */

Código: Seleccionar todo

void pspDebugScreenKprintf(const char* fmt, argumentos);
/* Esta función hace lo mismo que la anterior, pero es sólo para kernel mode.
Ejemplo: pspDebugScreenKprintf(“Hola, Mundo\!\n”); */

Código: Seleccionar todo

void pspDebugScreenEnableBackColor(int enable);
/* Esta función permite habilitar o deshabilitar la escritura del color de fondo de la pantalla.
@parámetro enable – Si es 1, está habilitado, si es 0, deshabilitado.
Ejemplo: pspDebugScreenEnableBackColor(1); */

Código: Seleccionar todo

void pspDebugScreenSetBackColor(u32 color);
/* Esta función permite determinar un color para el fondo de la pantalla.
@parámetro color – Color RGB de 32 bits.
Ejemplo: pspDebugScreenSetBackColor(0x00000000); */

Código: Seleccionar todo

void pspDebugScreenSetTextColor(u32 color);
/* Esta función permite determinar un color para el texto que se muestra.
@parámetro color – Color RGB de 32 bits.
Ejemplo: pspDebugScreenSetTextColor(0xFFFFFF); */

Código: Seleccionar todo

void pspDebugScreenSetColorMode(int mode);
/* Determina el modo de color a usar.
@parámetro mode – Modo de color, con los mismos que vimos para pspDebugScreenInitEx.
Ejemplo: pspDebugScreenSetColorMode(PSP_DISPLAY_PIXEL_FORMAT_8888); */

Código: Seleccionar todo

void pspDebugScreenPutChar(int x, int y, u32 color, u8 ch);
/* Dibuja un carácter único en pantalla. De esta manera,
@parámetro x – Coordenada X de la pantalla
@parámetro y – Coordenada Y de la pantalla
@parámetro color – Color de 32 bits para el carácter
@parámetro ch – El carácter a dibujar, entre comillas.
Ejemplo: pspDebugScreenPutChar(75, 43, 0x000000, ‘A’) */

Código: Seleccionar todo

void pspDebugScreenSetXY(int x, int y);
/* Define las coordenadas para impresion en pantalla.
@parámetro x – Coordenada X (todas estas coordenadas son en unidades de carácter)
@parámetro y – Coordenada Y
Ejemplo: pspDebugScreenSetXY(10, 20) */

Código: Seleccionar todo

void pspDebugScreenSetOffset(int offset);
/*Determina el offset de video a usar.
@parámetro offset – Nuestro offset.
Ejemplo: int offset
offset = vram32 - 0x40000000;
pspDebugScreenSetOffset(offset); */

Código: Seleccionar todo

void pspDebugScreenSetBase(u32* base);
/* Determina la base de video ram que se usa para la impresión en pantalla.
@parámetro base – Puntero a la base.
Ejemplo: static void* base = (u32 *) 0x44000000;
pspDebugScreenSetBase(base); */

Código: Seleccionar todo

int pspDebugScreenGetX(void);
/* Obtiene la coordenada X actual.
Ejemplo: pspDebugScreenGetX(); */

Código: Seleccionar todo

int pspDebugScreenGetY(void);
/* Obtiene la coordenada Y actual.
Ejemplo: pspDebugScreenGetY(); */

Código: Seleccionar todo

void pspDebugScreenClear(void);
/* Limpia la pantalla.
Ejemplo: pspDebugScreenClear(); */

Código: Seleccionar todo

int pspDebugScreenPrintData(const char* buff, int size);
/* Permite, cuando hay datos restantes en el buffer, imprimirlos.
@parámetro buff – Puntero al buffer con los datos.
@parámetro size – Tamaño de los datos.
Ejemplo: pspDebugScreenPrintData(buffer, 3); */

Código: Seleccionar todo

int pspDebugScreenPuts(const char* str);
/* Imprime en pantalla una cadena de texto.
@parámetro str – Cadena de texto.
Ejemplo: pspDebugScreenPuts(“heya look my string”); */

Código: Seleccionar todo

int pspDebugGetStackTrace(unsigned int* results, int max);
/* Una función algo inestable, que permite supuestamente devolver el total de las trazas almacenadas en la pila del procesador MIPS.
@parámetro results – Puntos a guardar los resultados (hasta el total de max)
@parámetro max – Máximo número de trazas
Ejemplo: pspDebugGetStackTrace(direccion, 512); */

Código: Seleccionar todo

int pspDebugInstallErrorHandler(PspDebugErrorHandler handler);
/* Dispone una marca para poder determinar errores y excepciones.
@parámetro handler – Puntero a la función handler. Si es nulo (NULL), resetea la pantalla y devuelve el error.
Ejemplo: pspDebugInstallErrorHandler(NULL); */

Código: Seleccionar todo

void pspDebugDumpException(PspDebugRegBlock *regs);
/* Dumpea el valor de un error/excepción en pantalla.
@parámetro regs – Puntero al bloque de registro.
Ejemplo: pspDebugDumpException(regs); */

Código: Seleccionar todo

int pspDebugInstallKprintfHandler(PspDebugKprintfHandler handler);
/* Determina un punto de escritura (en kernel)
@parámetro handler – Puntero al punto de escritura.
Ejemplo: pspDebugInstallKprintfHandler(NULL); */

Código: Seleccionar todo

int pspDebugGetStackTrace2(PspDebugRegBlock* regs, PspDebugStackTrace *trace, int max);
/* Permite hacer una traza de pila desde la excepción presente.
@parámetro regs – Puntero al bloque de registro con la excepción
@parámetro trace – Puntero a parte de la estructura de PspDebugStackTrace, donde puede ser:
_PspDebugStackTrace::call_addr (dirección llamada por la fun.)
_PspDebugStackTrace::func_addr (dirección de la función)
@parámetro max – Máximo número de trazas a realizar.
Ejemplo: pspDebugGetStackTrace2(regs, trace, 512); */

Código: Seleccionar todo

void pspDebugProfilerEnable(void);
/* Habilita el perfil de hardware de pantalla.
Ejemplo: pspDebugProfilerEnable(); */

Código: Seleccionar todo

void pspDebugProfilerDisable(void);
/* Deshabilita el perfil de hardware de pantalla.
Ejemplo: pspDebugProfilerDisable(); */

Código: Seleccionar todo

void pspDebugProfilerClear(void);
/* Limpia los registros existentes en perfiles de pantalla.
Ejemplo: pspDebugProfilerClear(); */

Código: Seleccionar todo

void pspDebugProfilerGetRegs(PspDebugProfilerRegs* regs);
/* Devuelve el estado de un registro de perfil.
@parámetro regs – Puntero a la estructura de PspDebugProfilerRegs, que van desde enable, systemck (check de sistema), internal, memory, … entre tantas otras.
Ejemplo: PspDebugProfilerGetRegs regs;
pspDebugProfilerGetRegs(&regs); */

Código: Seleccionar todo

void pspDebugProfilerPrint(void);
/* Imprime los registros de perfiles existentes a pantalla.
Ejemplo: pspDebugProfilerPrint(); */

Código: Seleccionar todo

int pspDebugInstallStdinHandler(PspDebugInputHandler handler);
/* Instala un punto de control para stdin y para conseguir el uso de stdio sin problemas.
@parámetro handler – Puntero al punto de control, NULL si se quiere deshabilitar.
Ejemplo: pspDebugInstallStdinHandler(NULL); */

Código: Seleccionar todo

int pspDebugInstallStdoutHandler(PspDebugInputHandler handler);
/* Instala un punto de control para stdout y para conseguir el uso de print sin problemas.
@parámetro handler – Puntero al punto de control, NULL si se quiere deshabilitar.
Ejemplo: pspDebugInstallStdinHandler(NULL); */

Código: Seleccionar todo

int pspDebugInstallStderrHandler(PspDebugInputHandler handler);
/* Instala un punto de control para stderr y para conseguir el uso de print sin problemas.
@parámetro handler – Puntero al punto de control, NULL si se quiere deshabilitar.
Ejemplo: pspDebugInstallStdinHandler(NULL); */

Código: Seleccionar todo

void pspDebugSioPutchar(int ch);
/*Dispone un carácter en el sio remoto.
@parámetro ch – Carácter a imprimir
Ejemplo: pspDebugSioPutChar(“A”); */

Código: Seleccionar todo

int pspDebugSioGetChar(void);
/* Devuelve el carácter almacenado en sio.
Ejemplo: pspDebugSioGetChar(); */

Código: Seleccionar todo

void pspDebugSioPuts(const char* str);
/* Escribe una cadena de texto al sio.
@parámetro str – Cadena de texto a imprimir
Ejemplo: pspDebugSioPuts(“heya look my string”); */

Código: Seleccionar todo

int pspDebugSioPutData(const char* data, int len);
/* Guarda en sio una cantidad determinada de datos.
@parámetro data – Puntero a los datos a guardar.
@parámetro len – Longitud de los datos.
Ejemplo: pspDebugSioPutData(data, length); */

Código: Seleccionar todo

int pspDebugSioPutText(const char* data, int len);
/* Guarda en sio una cantidad determinada de datos, convirtiendo líneas únicas de datos a CRLF y líneas de CR a CRLF.
@parámetro data – Puntero a los datos a guardar.
@parámetro len – Longitud de los datos.
Ejemplo: pspDebugSioPutText(data, length); */

Código: Seleccionar todo

void pspDebugSioInit(void);
/* Inicia el puerto remoto de SIO.
Ejemplo: pspDebugSioInit(); */

Código: Seleccionar todo

void pspDebugSioSetBaud(int baud);
/* Determina el ratio de baudio del Sio.
@parámetro baud – baudio, de 4800 a 115200.
Ejemplo: pspDebugSioSetBaud(4800); */

Código: Seleccionar todo

void pspDebugEnablePutChar(void);
/* Habilita la salida de caracteres por debug. Es necesario para el uso de las funciones de Kprintf.
Ejemplo: pspDebugEnablePutChar(); */

Código: Seleccionar todo

void pspDebugSioInstallKprintf(void);
/* Instala un punto de control de escritura con kprintf.
Ejemplo: pspDebugSioInstallKprintf(); */

Código: Seleccionar todo

void pspDebugGdbStubInit(void);
/* Instala un punto de control de GDB.
Ejemplo: pspDebugGdbStubInit(); */

Código: Seleccionar todo

void pspDebugBreakpoint(void);
/* Genera una excepción como punto de bloqueo.
Ejemplo: pspDebugBreakpoint(); */

Código: Seleccionar todo

void pspDebugSioEnableKprintf(void);
/* Una vez instalado el punto de control de kprintf, lo habilita.
Ejemplo: pspDebugSioEnableKprintf(); */

Código: Seleccionar todo

void pspDebugSioDisableKprintf(void);
/* Una vez instalado el punto de control de kprintf, lo deshabilita.
Ejemplo: pspDebugSioDisableKprintf(); */



Pues bien, sigamos con el apartado. Ahora, nos toca revisar los referentes al pspDisplay, de manera que tendremos que incluir una de las siguientes directivas:

Código: Seleccionar todo

#include <pspdisplay.h>
#include <pspdisplay_kernel.h>

y estas son sus funciones:

Código: Seleccionar todo

int sceDisplaySetMode(int mode, int width, int height);
/*Determina el modo de display.
@parámetro mode – Modo de display, generalmente 0.
@parámetro width – Anchura de la pantalla.
@parámetro height – Alto de la pantalla.
Ejemplo: sceDisplaySetMode(0, SCREEN_WIDTH, SCREEN_HEIGHT); */

Código: Seleccionar todo

int sceDisplayGetMode(int* pmode, int* pwidth, int* pheight);
/* Determina el modo actual.
@parámetro pmode – Puntero al modo.
@parámetro pwidth – Puntero al ancho.
@parámetro pheight – Puntero al alto.
Ejemplo: sceDisplayGetMode(&mode, &width, &height); */

Código: Seleccionar todo

int sceDisplaySetFrameBuf(void* topaddr, int bufferwidth, int pixelformat, int sync);
/* Determina el buffer para el display.
@parámetro topaddr – Dirección de inicio del buffer.
@parámetro bufferwidth – Tamaño del buffer, en potencia de dos.
@parámetro pixelformat – Uno de los formatos de color que vimos anteriormente.
@parámetro sync – O bien: (0 es nulo como siempre)
PSP_DISPLAY_SETBUF_IMMEDIATE (cambio inmediato en el buf)
PSP_DISPLAY_SETBUF_NEXTFRAME (cambio en el sig. Frame)
Ejemplo:
sceDisplaySetFrameBuf(&buff, 512, PSP_DISPLAY_PIXEL_FORMAT_8888, 0); */

Código: Seleccionar todo

int sceDisplayGetFrameBuf(void** topaddr, int* bufferwidth, int* pixelformat, int sync);
/* Obtiene la información del buffer de display.
@parámetro topaddr – Puntero al inicio del buffer.
@parámetro bufferwidth – Puntero al tamaño del buffer.
@parámetro pixelformat – Puntero al formato.
@parámetro sync – Uno de los anteriores.
Ejemplo: sceDisplayGetFrameBuf(&buff, &buffwidth, &format, 0); */

Código: Seleccionar todo

unsigned int sceDisplayGetVcount(void);
/* Devuelve el número de veces que ha habido una cuenta en blanco, es decir, como en un conteo de frames.
Ejemplo: sceDisplayGetVcount(); */

Código: Seleccionar todo

int sceDisplayWaitVblankStart(void);
/* Espera a que inicie un conteo de los anteriores.
Ejemplo: sceDisplayWaitVblankStart(); */

Código: Seleccionar todo

int sceDisplayWaitVblankStartCB(void);
/* Igual que anteriormente pero con un callback, es decir, teniendo en cuenta lo que ha sucedido anteriormente.
Ejemplo: sceDisplayWaitVblankStartCB(); */

Código: Seleccionar todo

int sceDisplayWaitVblank(void);
/* Espera a un conteo de los anteriores.
Ejemplo: sceDisplayWaitVblank(); */

Código: Seleccionar todo

int sceDisplayWaitVblankCB(void);
/* Igual que anteriormente pero con un callback, es decir, teniendo en cuenta lo que ha sucedido anteriormente.
Ejemplo: sceDisplayWaitVblankCB(); */

Código: Seleccionar todo

void sceDisplaySetBrightness(int level, int unk1);
/* Determina el brillo de la pantalla.
@parámetro level – Nivel de brillo de 0 a 100
@parámetro unk1 – Desconocido, habitualmente 0.
Ejemplo: sceDisplaySetBrightness(100, 0); */

Código: Seleccionar todo

void sceDisplayGetBrightness(int* level, int* unk1);
/* Obtiene los valores mediante punteros del brillo.
@parámetro level – Puntero al nivel de brillo.
@parámetro unk1 – Puntero al valor
Ejemplo: sceDisplayGetBrightmess(&level, 0); */



Y con ello, podríamos concluir fácilmente con esos dos módulos, pspDebug y pspDisplay.



Hola, Mundo!:

Spoiler:
No podría quedarme sin mencionar este tema.

Aunque por lo general soy bastante reticente a creer que es necesario nada de esto para poder comprender mejor todo lo que utilizamos... qué demonios. Vamos a verlo en un momento.

Utilizando las funciones y los ejemplos que hemos visto anteriormente, podríamos tener este main.c:

Código: Seleccionar todo

/* Hello, World! Nuestro primer programa en PSP.
Creado el día XX del mes XX del año XXXX
En él, vemos cómo mostrar en pantalla una simple frase. */
// Directivas del preprocesador
#include <pspkernel.h>
#include <pspsdk.h>
/* El pspkernel.h así como el pspsdk.h es una directiva necesaria. Es cierto, no la hemos visto aún, pero ya que es necesaria, es mejor disponerla para que veais que en realidad sí que se puede programar, y en el futuro la explicaremos más detalladamente, ya que con vuestros conocimientos actuales no entenderíais la mitad de lo que hace. Por ahora, consideradla como algo imperativo para que vuestro programa funcione, ya que contiene las funciones más habituales de uso, registro, manejo de datos y de errores. */
#include <pspdebug.h> // Si, precisamente lo que acabamos de ver.

// Nuestro programa se llamará “Mi Hello World”, está en modo User (0), y la versión es 1.0
PSP_MODULE_INFO(“Mi Hello World”, 0, 1, 0);
// Modo user del thread principal...
PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER);

// Defines.
// Si, podríamos poner, pero va a ser que no, que así no se aprende :-P

// Programa principal.
int main(void) {
// Es decir, el main thread que devuelve un void...
pspDebugScreenInit(); // Referios a las páginas anteriores
pspDebugScreenSetTextColor(0xFFFFFFFF); // Referios a las páginas anteriores
pspDebugScreenPrintf(“Hola, Mundo\n”); // Referios a las páginas anteriores
return 0; // Devolviendo el control.
}

y, de igual manera, el Makefile para ese main.c sería el siguiente:

Código: Seleccionar todo

# Target, el nombre reducido de nuestro programa, preferentemente en minúsculas...
TARGET = hola
# Objs, los objetos a linkear (Tenemos sólo main.c, por lo que main.o)
OBJS = main.o
# Librerias a incluir… en nuestro caso la propia al haber incluido el
# pspsdk.h;
LIBS = -lpspsdk
# Flags de compilación. Usamos estos generales casi por convención,
# es decir,
CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
# De cualquier manera los veremos con calma en otro curso, en C.
# Determinantes extras
EXTRA_TARGETS = EBOOT.PBP
# El nombre efectivo de nuestro programa que se mostrará en el XMB
PSP_EBOOT_TITLE = Hola Mundo
# Y nuestras lineas obligatorias para que pille la compilación del SDK.
PSPSDK=$(shell psp-config –pspsdk-path)
include $(PSPSDK)/lib/build.mak


Pues bien, guardamos ambos con sus nombres (main.c , Makefile) en un directorio en nuestra carpeta de Cygwin o bajo GNU/Linux, y hacemos un simple:

Código: Seleccionar todo

$ make

tras lo que tendremos un EBOOT.PBP en la misma carpeta donde hemos compilado.

Más tarde, copiamos ese EBOOT.PBP a nuestra ms0:/PSP/GAME/ y lo ejecutamos desde Juegos - Memory Stick. Si veis un "Hola, Mundo!" en la pantalla, podéis respirar tranquilos. Ya ha pasado lo peor. ¿O no?
hello.7z



Librerías Oficiales: pspCtrl:

Spoiler:
El módulo pspCtrl definido por las siguientes directivas:

Código: Seleccionar todo

#include <pspctrl.h>
#include <pspctrl_kernel.h>

incluye una serie de funciones y carácteres que nos ayudarán a manejar todos los controles de nuestra PSP.

Código: Seleccionar todo

struct unsigned int SceCtrlData :: TimeStamp // El estado actual de lectura
unsigned int SceCtrlData :: Buttons // Algún o ningún boton.
unsigned char SceCtrlData :: Lx // Eje X del Análogo
unsigned char SceCtrlData :: Ly // Eje Y del Análogo
unsigned char SceCtrlData :: Rsrv // Reservado

Código: Seleccionar todo

enum PspCtrlButtons {
PSP_CTRL_SELECT = 0x000001 // Select
PSP_CTRL_START = 0x000008 // Start
PSP_CTRL_UP = 0x000010 // Arriba en el pad digital
PSP_CTRL_RIGHT = 0x000020 // Derecha en el pad digital
PSP_CTRL_DOWN = 0x000040 // Abajo en el pad digital
PSP_CTRL_LEFT = 0x000080 // Izquierda en el pad digital
PSP_CTRL_LTRIGGER = 0x000100 // Disparador izquierdo
PSP_CTRL_RTRIGGER = 0x000200 // Disparador derecho
PSP_CTRL_TRIANGLE = 0x001000 // Triángulo
PSP_CTRL_CIRCLE = 0x002000 // Círculo
PSP_CTRL_CROSS = 0x004000 // Equis
PSP_CTRL_SQUARE = 0x008000 // Cuadrado
PSP_CTRL_HOME = 0x010000 // Home. Sólo kernel.
PSP_CTRL_HOLD = 0x020000 // Hold.
PSP_CTRL_NOTE = 0x800000 // Nota musical. Sólo kernel.
PSP_CTRL_SCREEN = 0x400000 // Pantalla. Sólo kernel.
PSP_CTRL_VOLUP = 0x100000 // Volumen arriba. Sólo kernel.
PSP_CTRL_VOLDOWN = 0x200000 // Volumen abajo. Sólo kernel.
PSP_CTRL_WLAN_UP = 0x040000 // Wlan. Sólo kernel.
PSP_CTRL_REMOTE = 0x080000 // Remote. Sólo kernel.
PSP_CTRL_DISC = 0x100000 // Disco presente. Sólo kernel.
PSP_CTRL_MS = 0x200000 // MS presente Sólo kernel.
}

Código: Seleccionar todo

enum PspCtrlMode {
PSP_CTRL_MODE_DIGITAL = 0 // Modo digital
PSP_CTRL_MODE_ANALOG = 1 // Modo analógico
}

Código: Seleccionar todo

int sceCtrlSetSamplingCycle (int cycle);
/*Esta función se utiliza para controlar el ciclo de los botones, o lo que es lo mismo, el ciclo de pulsaciones.
@parámetro cycle – Ciclo de pulsaciones. Por lo general, es adecuado dejarlo en 0, pero se puede elevar hasta niveles estrambóticos para solucionar problemas de pulseo.
Ejemplo: sceCtrlSetSamplingCycle(0); */

Código: Seleccionar todo

int sceCtrlGetSamplingCycle(int *pcycle);
/* Devuelve el ciclo de pulsaciones hecho por defecto.
@parámetro *pcycle – Puntero a los ciclos de pulsaciones.
Ejemplo: sceCtrlGetSamplingCycle(&cycle); */

Código: Seleccionar todo

int sceCtrlSetSamplingMode(int mode);
/* Determina el modo de control.
@parámetro mode – Uno de los modos que vimos en el PspCtrlMode.
Ejemplo: sceCtrlSetSamplingMode(PSP_CTRL_MODE_DIGITAL); */

Código: Seleccionar todo

int sceCtrlGetSamplingMode(int *pmode);
/* Devuelve el modo de control actual.
@parámetro *pmode – Puntero al modo de control.
Ejemplo: sceCtrlGetSamplingMode(&mode); */

Código: Seleccionar todo

int sceCtrlPeekBufferPositive(SceCtrlData *pad_data, int count);
/* Esta función nos permite leer los valores que son presionados (y por tanto en buffer), de una manera rápida y simple.
@parámetro *pad_data – Puntero a la SceCtrlData que almacena los datos obtenidos por la misma estructura.
@parámetro count – Número de buffers del pad_data a leer.
Ejemplo: SceCtrlData pad;
sceCtrlPeekBufferPositive(&pad, 1); */

Código: Seleccionar todo

int sceCtrlPeekBufferNegative(SceCtrlData *pad_data, int count);
/* Esta función, prácticamente contraria a la anterior, nos indica los valores que NO han sido presionado tras pasar por SceCtrlData.
@parámetro *pad_data – Puntero a la SceCtrlData que almacena los datos obtenidos por la misma estructura.
@parámetro count – Número de buffers del pad_data a leer.
Ejemplo: SceCtrlData pad;
SceCtrlPeekBufferNegative(&pad, 1); */

Código: Seleccionar todo

int sceCtrlReadBufferPositive(SceCtrlData *pad_data, int count);
/* Esta función es prácticamente igual que las Peek, pero espera al VBlank, de manera que será sustancialmente más lenta.
@parámetro *pad_data – Puntero a la SceCtrlData que almacena los datos obtenidos por la misma estructura.
@parámetro count – Número de buffers del pad_data a leer.
Ejemplo: SceCtrlData pad;
sceCtrlReadBufferPositive(&pad, 1); */

Código: Seleccionar todo

int sceCtrlReadBufferNegative(SceCtrlData *pad_data, int count);
/* Esta función es prácticamente igual que las Peek, pero espera al VBlank, de manera que será sustancialmente más lenta.
@parámetro *pad_data – Puntero a la SceCtrlData que almacena los datos obtenidos por la misma estructura.
@parámetro count – Número de buffers del pad_data a leer.
Ejemplo: SceCtrlData pad;
sceCtrlReadBufferNegative(&pad, 1); */

Código: Seleccionar todo

int sceCtrlSetIdleCancelThreshold(int idlereset, int idleback);
/* Esta función permite determinar el tiempo que implicará hasta que la pantalla se oscurezca, es decir, el tiempo de “idle”.
@parámetro idlereset – Movimiento necesario para que el contador se ponga a cero.
@parámetro idleback – Movimiento necesario para que se salga del idle.
Si se quiere que no exista idle, el valor en ambos puede ser igual.
Ejemplo: sceCtrlSetIdleCancelThreshold(20,20); */

Código: Seleccionar todo

int sceCtrlGetIdleCancelThreshold(int *idlereset, int *idleback);
/* Devuelve el tiempo hasta el idle.
@parámetro *idlereset – Puntero al movimiento necesario para que el contador se ponga a cero.
@parámetro *idleback – Puntero al movimiento necesario para que se salga del idle.
Ejemplo: sceCtrlGetIdleCancelThreshold(&reset,&back); */


Podríamos tener un ejemplo del uso de esta librería con el siguiente caso: Nuestro main.c:

Código: Seleccionar todo

/* Programa de ejemplo - Uso de funciones del pspctrl.h

Curso de Programación en C para PSP - www.Dark-AleX.org

--Alek */

#include <pspkernel.h>
#include <pspdebug.h>    // Nuestro debug, os acordais?
#include <pspctrl.h>     // Aquí nuestro recién llegado.
#include <stdio.h>
#include <stdlib.h>

PSP_MODULE_INFO("Prueba de Botones", 0, 1, 0); // En user.


int main (void)   {                         // Main thread
    SceCtrlData pad;
    sceCtrlSetSamplingCycle(0);
    sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);

    pspDebugScreenInit();             // Iniciando la pantalla, recordais?
    pspDebugScreenPrintf("\nPresiona START para salir.\n\n\n");
    pspDebugScreenPrintf("Presiona cualquier boton del pad.\n\n\n");
    /* Si os poneis monos, incluso se podrían cambiar los colores de fondo y
    de texto, pero eso os lo dejo a vosotros */

                     
   while(1)    {         // Inicializando botones
      sceCtrlReadBufferPositive(&pad, 1);   
               
                if(pad.Buttons & PSP_CTRL_CROSS){
                               pspDebugScreenPrintf("Has presionado la X\n");
                }
               
                if(pad.Buttons & PSP_CTRL_SQUARE){
                               pspDebugScreenPrintf("Has presionado el []\n");
                }
               
                if(pad.Buttons & PSP_CTRL_TRIANGLE){
                               pspDebugScreenPrintf("Has presionado el /\\\n");
                }
               
                if(pad.Buttons & PSP_CTRL_CIRCLE){
                               pspDebugScreenPrintf("Has presionado el O\n");
                }
               
                if(pad.Buttons & PSP_CTRL_START){
                               sceKernelExitGame();
                }
               
                /* Y demás. Obviamente podríamos seguir con el resto de botones,
                pero recordad que hay algunos que necesitan kernel, y estamos
                en user, de ahi que usemos START para salir, y no HOME. De esa
                manera, se resume así:
               
                if(pad.Buttons & BOTON_A_PRESIONAR){
                               Lo que va a pasar cuando presionemos
                }
               
                Recordad claro está que para que todo esto funcione, tenemos que
                tener cargado todo en buffer (ya sea con Peek o con Read), y
                determinado el modo de lectura (análoga o digital), con el ciclo
                de pulsaciones.
            
            De igual manera, tened en cuenta el hecho de los pad.Buttons, una
            especie de trigger que usamos para inicializarlos, algo que sólo
            se podía explicar con un ejemplo como este.*/
    }   
    return 0;
}

y nuestro Makefile:

Código: Seleccionar todo

TARGET  =   pruebabotones
OBJS    =   pspctrl_ejemplo.o

CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

LIBS = -lpspctrl

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Uso de funciones del pspctrl.h

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak

pspctrl.7z



Librerías Oficiales: pspUmd:

Spoiler:
La librería pspUmd, definida por la siguiente directiva:

Código: Seleccionar todo

#include <pspumd.h>

nos indica información acerca del lector UMD, de los discos UMD presentes, y hacer todo tipo de virguerías con ellos, con las funciones que tiene:

Código: Seleccionar todo

struct unsigned int pspUmdInfo :: size // Tamaño
unsigned int pspUmdInfo :: type // Ver pspUmdTypes.

Código: Seleccionar todo

enum pspUmdTypes {
PSP_UMD_TYPE_GAME = 0x10 // UMD de Juegos
PSP_UMD_TYPE_VIDEO = 0x20 // UMD de Videos
PSP_UMD_TYPE_AUDIO = 0x40 // UMD de Audio
}

Código: Seleccionar todo

enum pspUmdState {
PSP_UMD_NOT_PRESENT = 0x01 // UMD no está presente
PSP_UMD_PRESENT = 0x02 // UMD presente
PSP_UMD_CHANGED = 0x04 // Cambio de UMD
PSP_UMD_INITING = 0x08 // UMD iniciándose
PSP_UMD_INITED = 0x10 // UMD inicado
PSP_UMD_READY = 0x20 // UMD listo
}

Código: Seleccionar todo

enum UmdDriveStat {
UMD_WAITFORDISC = PSP_UMD_PRESENT // Buscando UMD
UMD_WAITFORINIT = PSP_UMD_READY // Esperando a que esté listo
}

Código: Seleccionar todo

int sceUmdCheckMedium(void);
/* Esta función nos permite comprobar si existe algún disco presente el dispositivo de UMD.
Ejemplo: sceUmdCheckMedium(); */

Código: Seleccionar todo

int sceUmdGetDiscInfo(pspUmdInfo *info);
/* Nos devuelve la información del disco obtenida desde pspUmdInfo, como vimos.
@parámetro *info – Puntero a la estructura de pspUmdInfo
Ejemplo: sceUmdGetDiscInfo(&info); */

Código: Seleccionar todo

int sceUmdActivate (int unit, const char *drive);
/* Activa el propio lector de UMDs.
@parámetro unit – Unidad a activar. De forma general a 1.
@parámetro *drive – Prefijo de montaje. Por ejemplo, disc0:
Ejemplo: sceUmdActivate(1, “disc0:”); */

Código: Seleccionar todo

int sceUmdDeactivate (int unit, const char *drive);
/* Desactiva el propio lector de UMDs.
@parámetro unit – Unidad a activar. De forma general a 1.
@parámetro *drive – Prefijo de montaje. Por ejemplo, disc0:
Ejemplo: sceUmdDeactivate(1, “disc0:”); */

Código: Seleccionar todo

int sceUmdWaitDriveStat(int stat);
/* Dispone una espera hasta que el lector de UMD se encuentre en un estado determinado.
@parámetro stat – Uno de los que vimos en pspUmdState
Ejemplo: sceUmdWaitDriveStat(PSP_UMD_NOT_PRESENT); */

Código: Seleccionar todo

int sceUmdWaitDriveStatWithTimer(int stat, unsigned int timeout);
/* Dispone una espera hasta que el lector de UMD se encuentre en un estado determinado, con un periodo máximo de espera.
@parámetro stat – Uno de los que vimos en pspUmdState
@parámetro timeout – Tiempo máximo de espera en microsegundos.
Ejemplo: sceUmdWaitDriveStatWithTimer(PSP_UMD_NOT_PRESENT, 100);*/

Código: Seleccionar todo

int sceUmdWaitDriveStatCB(int stat, unsigned int timeout);
/* Dispone una espera hasta que el lector de UMD se encuentre en un estado determinado, con un periodo máximo de espera, y un callback.
@parámetro stat – Uno de los que vimos en pspUmdState
@parámetro timeout – Tiempo máximo de espera en microsegundos.
Ejemplo: sceUmdWaitDriveStatCB(PSP_UMD_NOT_PRESENT, 100); */

Código: Seleccionar todo

int sceUmdCancelWaitDriveStat(void);
/* Tras haber sido inicializada una función del tipo sceUmdWait*, la cancela.
Ejemplo: sceUmdCancelWaitDriveStat(); */

Código: Seleccionar todo

int sceUmdGetDriveStat(void);
/* Devuelve el estado actual del lector.
Ejemplo: sceUmdGetDriveStat(); */

Código: Seleccionar todo

int sceUmdGetErrorStat(void);
/* En el caso de error, devuelve el código del mismo.
Ejemplo: sceUmdGetErrorStat(); */

Código: Seleccionar todo

int sceUmdRegisterUMDCallback(int cbid);
/* Registra un callback del lector de UMD
@parámetro cbid – Callback determinado anteriormente.
Ejemplo: int cbid = sceKernelCreateCallback(“UMD”, umd, NULL);
sceUmdRegisterUMDCallback(cbid); */

Código: Seleccionar todo

int sceUmdUnRegisterUMDCallback(int cbid);
/* Elimina el registro un callback del lector de UMD
@parámetro cbid – Callback determinado anteriormente.
Ejemplo: sceUmdUnRegisterUMDCallback(cbid); */

Código: Seleccionar todo

int sceUmdReplacePermit(void);
/* Permite que el UMD sea cambiado por otro.
Ejemplo: sceUmdReplacePermit(); */

Código: Seleccionar todo

int sceUmdReplaceProhibit(void);
/* Prohibe que el UMD sea cambiado por otro.
Ejemplo: sceUmdReplaceProhibit(); */


Un ejemplo del funcionamiento de esta librería lo podemos ver aquí, siendo este nuestro main.c:

Código: Seleccionar todo

/* Programa de ejemplo - Uso de funciones del pspumd.h

Curso de Programación en C para PSP - www.Dark-AleX.org

--Alek */

#include <pspkernel.h>
#include <pspdebug.h>      
#include <pspctrl.h>      
#include <pspumd.h>         // El recién llegado
#include <stdio.h>
#include <stdlib.h>

PSP_MODULE_INFO("Prueba de UMD", 0, 1, 0); // En user.



int main (void)   {         
    SceCtrlData pad;
    sceCtrlSetSamplingCycle(0);
    sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);

    pspDebugScreenInit();   
    pspDebugScreenPrintf("\nPresiona START para salir.\n\n\n");
    pspDebugScreenPrintf("Presiona X para empezar la prueba.\n\n\n");
                     
   while(1)   {
      sceCtrlReadBufferPositive(&pad, 1);
      
      if(pad.Buttons & PSP_CTRL_CROSS){
         int check;
         check = sceUmdCheckMedium();
         if (check==0) {      // Si NO hay un UMD dentro
         pspDebugScreenPrintf("No hay ningun disco UMD insertado\n");
         pspDebugScreenPrintf("Inserta un disco...\n\n");
         sceUmdWaitDriveStat(UMD_WAITFORDISC);
         /* Esperando a ver si se introduce o no un disco. Dirigido a
         UMD_WAITFORDISC que si recordais se asociaba a
         PSP_UMD_PRESENT del pspUmdState. En el caso de que no se introduzca,
         no pasará de este estado.*/
         pspDebugScreenPrintf("Disco insertado. Gracias.\n\n");
         }
         
         // Una vez comprobado que hay un disco, seguimos.
         sceUmdActivate(1, "disc0:");      // Activando el lector.
         sceUmdWaitDriveStat(UMD_WAITFORINIT);
         /* Esperando a que el UMD esté preparado, dirigido a UMD_WAITFORINIT
         que está vinculado a PSP_UMD_READY del pspUmdState. En el caso de que
         no se active, no pasará de este punto.*/
         pspDebugScreenPrintf("Disco inicializado. Gracias.\n\n");
         pspDebugScreenPrintf("Desactivando lector...\n");
         sceUmdDeactivate(1, "disc0:");      // Desactivando el lector.
         
         pspDebugScreenPrintf("Ahora, cambie el disco por otro.\n");
         sceUmdWaitDriveStat(PSP_UMD_NOT_PRESENT);   // Esperando a que el UMD no esté.
         pspDebugScreenPrintf("UMD quitado. Introduzca el otro.\n");
         sceUmdReplacePermit();                  // Permitiendo el cambio
         /* Aquí podríamos incluir facilmente una condición para que compruebe si el UMD
         se ha cambiado efectivamente, es decir, si el UMD es distinto al primero,
         guardando los datos de sceUmdGetDiscInfo, pero eso os lo dejo a vosotros como tarea */
         sceUmdWaitDriveStat(PSP_UMD_PRESENT);      // Esperando a que el nuevo UMD esté.
         pspDebugScreenPrintf("Gracias, disco cambiado. Activando el lector...\n");
         sceUmdActivate(1, "disc0:");      // Activando el lector.
         sceUmdWaitDriveStat(UMD_WAITFORINIT);
         pspDebugScreenPrintf("Disco inicializado. Gracias.\n\n");
         
         pspDebugScreenPrintf("Pruebas concluidas.\n\n");
         
         pspDebugScreenPrintf("Desactivando lector...\n");
         sceUmdDeactivate(1, "disc0:");      // Desactivando el lector.
         pspDebugScreenPrintf("Lector desactivado, quite el disco, por favor...\n");
         sceUmdWaitDriveStat(PSP_UMD_NOT_PRESENT);   // Esperando a que el UMD no esté.
      }   
         
      if(pad.Buttons & PSP_CTRL_START){
         sceKernelExitGame();
      }
    }   
    return 0;
}

y este nuestro Makefile:

Código: Seleccionar todo

TARGET  =   pspumd
OBJS    =   pspumd_ejemplo.o

CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

LIBS = -lpspctrl -lpspumd

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Uso de funciones del pspumd.h

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak

pspumd.7z



Librerías Oficiales: pspIoFileMgr:

Spoiler:
La librería pspIoFileMgr, aunque no veremos ningún ejemplo de ella por ahora ya que hará falta un estudio más detallado de las librerías de pspkernel, nos permite el manejo de entrada y salida de archivos y carpetas, todo tipo de operaciones.

Estas son sus funciones:

Código: Seleccionar todo

enum IoAssignPerms {
IOASSIGN_RDWR // Asignación en lectura y escritura.
IOASSIGN_RDONLY // Asignación en sólo lectura.
}

Código: Seleccionar todo

#define PSP_O_RDONLY 0x0001 // Sólo lectura.
#define PSP_O_WRONLY 0x0002 // Sólo escritura.
#define PSP_O_RDWR 0x0003 // Lectura y escritura.
#define PSP_O_NBLOCK 0x0004 //
#define PSP_O_DIROPEN 0x0008 // Uso interno de directorios.
#define PSP_O_APPEND 0x0100 // Se dirige al final del archivo.
#define PSP_O_CREAT 0x0200 // Crea el archivo si no existe.
#define PSP_O_TRUNC 0x0400 // Trunca el archivo.
#define PSP_O_EXCL 0x0800 //
#define PSP_O_NOWAIT 0x8000 //
#define PSP_SEEK_SET 0
#define PSP_SEEK_CUR 1
#define PSP_SEEK_END 2
/* Estos tres últimos PSP_SEEK_* indican el lugar de búsqueda para archivos, como veremos en las funciones posteriores. SET indica el inicio del archivo, CUR indica la posición actual, y END indica la posición final del archivo. */

Código: Seleccionar todo

SceUID sceIoOpen(const char *file, int flags, SceMode mode);
/* Permite abrir un archivo para su lectura y/o escritura.
@parámetro *file – Puntero a la dirección del archivo.
@parámetro flags – flags de permisos que vimos en la página anterior.
@parámetro mode – Modo de acceso al archivo.
Ejemplo:
fd = sceIoOpen(“ms0://file.bin”, PSP_O_RDWR | PSP_O_TRUNC, 0777); */

Código: Seleccionar todo

SceUID sceIoOpenAsync(const char *file, int flags, SceMode mode);
/* Permite abrir un archivo para su lectura y/o escritura, de forma asincrónica, es decir, tras conocer que las operaciones pendientes anteriores se han completado.
@parámetro *file – Puntero a la dirección del archivo.
@parámetro flags – flags de permisos que vimos en la página anterior.
@parámetro mode – Modo de acceso al archivo.
Ejemplo:
fd = sceIoOpenAsync(“ms0:/ / file.bin”, PSP_O_RDWR | PSP_O_TRUNC, 0777); */

Código: Seleccionar todo

int sceIoClose(SceUID fd);
/* Cierra un archive y elimina su registro.
@parámetro fd – Descriptor a cerrar.
Ejemplo: sceIoClose(fd); */

Código: Seleccionar todo

int sceIoCloseAsync(SceUID fd);
/* Cierra un archive y elimina su registro, de forma asincrónica.
@parámetro fd – Descriptor a cerrar.
Ejemplo: sceIoCloseAsync(fd); */

Código: Seleccionar todo

int sceIoRead(SceUID fd, void *data, SceSize size);
/* Lee una entrada determinada de un descriptor iniciado.
@parámetro fd – Descriptor ya abierto.
@parámetro data – Puntero al buffer donde se guardarán los datos.
@parámetro size – Tamaño de la lectura (bytes)
Ejemplo: sceIoRead(fd, buffer, size); */

Código: Seleccionar todo

int sceIoReadAsync(SceUID fd, void *data, SceSize size);
/* Lee una entrada determinada de un descriptor iniciado, de forma asincrónica.
@parámetro fd – Descriptor ya abierto.
@parámetro data – Puntero al buffer donde se guardarán los datos.
@parámetro size – Tamaño de la lectura (bytes)
Ejemplo: sceIoReadAsync(fd, buffer, size); */

Código: Seleccionar todo

int sceIoWrite(SceUID fd, const void *data, SceSize size);
/* Escribe algo dado en el descriptor abierto.
@parámetro fd – Descriptor ya abierto.
@parámetro data – Puntero al buffer donde se escribirán los datos.
@parámetro size – Tamaño en bytes de lo que se escribirá.
Ejemplo: sceIoWrite(fd, buffer, size); */

Código: Seleccionar todo

int sceIoWriteAsync(SceUID fd, const void *data, SceSize size);
/* Escribe algo dado en el descriptor abierto, de forma asincrónica
@parámetro fd – Descriptor ya abierto.
@parámetro data – Puntero al buffer donde se escribirán los datos.
@parámetro size – Tamaño en bytes de lo que se escribirá.
Ejemplo: sceIoWriteAsync(fd, buffer, size); */

Código: Seleccionar todo

SceOff sceIoLseek(SceUID fd, SceOff offset, int whence);
/*Permite situar la lectura/escritura en un punto dado.
@parámetro fd – Descriptor abierto anteriormente.
@parámetro offset – Offset a partir del cual se iniciará la lectura, una vez considerado el whence.
@parámetro whence – Punto de partida. Puede ser uno de los PSP_SEEK_* que vimos anteriormente.
Ejemplo: fd = sceIoOpen(“ms0: //ejemplo.bin”, PSP_O_RDWR, 0777);
sceIoLseek(fd, 100, PSP_SEEK_END); */

Código: Seleccionar todo

SceOff sceIoLseek32(SceUID fd, SceOff offset, int whence);
/*Permite situar la lectura/escritura en un punto dado, en modo de 32 bits.
@parámetro fd – Descriptor abierto anteriormente.
@parámetro offset – Offset a partir del cual se iniciará la lectura, una vez considerado el whence.
@parámetro whence – Punto de partida. Puede ser uno de los PSP_SEEK_* que vimos anteriormente.
Ejemplo: fd = sceIoOpen(“ms0: //ejemplo.bin”, PSP_O_RDWR, 0777);
sceIoLseek32(fd, 100, PSP_SEEK_END); */

Código: Seleccionar todo

SceOff sceIoLseekAsync(SceUID fd, SceOff offset, int whence);
/*Permite situar la lectura/escritura en un punto dado, de forma asincrónica.
@parámetro fd – Descriptor abierto anteriormente.
@parámetro offset – Offset a partir del cual se iniciará la lectura, una vez considerado el whence.
@parámetro whence – Punto de partida. Puede ser uno de los PSP_SEEK_* que vimos anteriormente.
Ejemplo: fd = sceIoOpen(“ms0: //ejemplo.bin”, PSP_O_RDWR, 0777);
sceIoLseekAsync(fd, 100, PSP_SEEK_END); */

Código: Seleccionar todo

SceOff sceIoLseek32Async(SceUID fd, SceOff offset, int whence);
/*Permite situar la lectura/escritura en un punto dado, de forma asincrónica y para 32 bits.
@parámetro fd – Descriptor abierto anteriormente.
@parámetro offset – Offset a partir del cual se iniciará la lectura, una vez considerado el whence.
@parámetro whence – Punto de partida. Puede ser uno de los PSP_SEEK_* que vimos anteriormente.
Ejemplo: fd = sceIoOpen(“ms0: //ejemplo.bin”, PSP_O_RDWR, 0777);
sceIoLseek(fd, 100, PSP_SEEK_END); */

Código: Seleccionar todo

int sceIoRemove(const char *file);
/* Elimina la entrada.
@parámetro file – Dirección a la entrada a eliminar.
Ejemplo: sceIoRemove(“ms0: //ejemplo.bin”); */

Código: Seleccionar todo

int sceIoMkdir(const char *dir, SceMode mode);
/* Crea un directorio.
@parámetro dir – Direccion de creación del directorio
@parámetro mode – Modo de creación.
Ejemplo: sceIoMkdir(“ms0://testdir”, 0777); */

Código: Seleccionar todo

int sceIoRmdir(const char *path);
/* Elimina un directorio dado.
@parámetro path – Dirección del directorio.
Ejemplo: sceIoRmdir(“ms0://testdir”); */

Código: Seleccionar todo

int sceIoChdir(const char *path);
/* Cambia el directorio en el que se encuentra actualmente.
@parámetro path – Dirección del directorio.
Ejemplo: sceIoChdir(“ms0://testdir2”); */

Código: Seleccionar todo

int sceIoRename(const char *oldname, const char *newname);
/* Renombra el archivo dado.
@parámetro oldname – Dirección antigua del archivo
@parámetro newname – Dirección nueva del archivo
Ejemplo: sceIoRename(“ms0://testdir2”, “ms0://testdir3”); */

Código: Seleccionar todo

SceUID sceIoDopen(const char *dirname);
/* Abre un directorio.
@parámetro dirname – Dirección al directorio.
Ejemplo: sceIoDopen(“ms0://testdir”); */

Código: Seleccionar todo

int sceIoDread(SceUID fd, SceIoDirent *dir);
/* Lee una entrada de un descriptor ya analizado.
@parámetro fd – Descriptor abierto
@parámetro dir – Puntero a un SceIoDirent para almacenar la información.
Ejemplo: SceIoDirent ent;
int fd;
fd = sceIoDopen(“ms0://testdir”);
sceIoDread(fd, &ent); */

Código: Seleccionar todo

int sceIoDclose(SceUID fd);
/* Cierra un descriptor de directorio abierto.
@parámetro fd – Descriptor abierto.
Ejemplo: sceIoDclose(fd); */

Código: Seleccionar todo

int sceIoDevctl(const char *dev, unsigned int cmd, void *indata, int inlen, void *outdata, int outlen);
/* Permite emitir y recibir comandos de y hacia los dispositivos.
@parámetro *dev – Dispositivo al que se va a mandar o recibir.
@parámetro cmd – Comando a enviar
@parámetro *indata – Bloque de datos a enviar, en otro caso es nulo (NULL)
@parámetro inlen – Longitud de indata, si es nulo, será 0.
@parámetro *outdata – Bloque de datos a recibir, en otro caso será nulo (NULL)
@parámetro outlen – Longitud de outdata, si es nulo, será 0.
Ejemplo: int *buffer;
sceIoDevctl(“ms0:”, 0x02425818,&buffer, sizeof(buffer),0,0); */

Código: Seleccionar todo

int sceIoAssign(const char *dev1, const char *dev2, const char *dev3, int mode, void *unk1, long unk2);
/* Permite asignar un dispositivo a un sistema de archives para poder ser manipulado.
@parámetro dev1 – Alias del dispositivo a asignar, sea el nombre que sea.
@parámetro dev2 – Dispositivo que se quiere asignar.
@parámetro dev3 – Sistema de archivos al que se quiere asignar.
@parámetro mode – Uno de los modos de IOASSIGN_* que hemos visto.
@parámetro unk1 – Desconocido, NULL por defecto.
@parámetro unk2 – Desconocido, 0 por defecto.
Ejemplo:
sceIoAssign(“UMD:”, “umd0:”, “isofs0”, IOASSIGN_RDONLY, NULL, 0); */

Código: Seleccionar todo

int sceIoUnassign(const char *dev);
/* Quita la asignación de un dispositivo.
@parámetro dev – Dispositivo asignado.
Ejemplo: sceIoUnassign(“UMD:”); */

Código: Seleccionar todo

int sceIoGetStat(const char *file, SceIoStat *stat);
/* Determina el estado de un archivo dado.
@parámetro *file – Dirección al archivo
@parámetro *stat – Puntero a un estado de SceIoStat.
Ejemplo: SceIoStat stt;
char file[256];
sceIoGetStat(file, &stt); */

Código: Seleccionar todo

int sceIoChStat(const char *file, SceIoStat *stat, int bits);
/* Cambia el estado de un archive en cuestión.
@parámetro *file – Dirección al archivo
@parámetro *stat – Puntero a un estado de SceIoStat.
@parámetro bits – Bits a cambiar.
Ejemplo: sceIoChStat(“flash0:/kd”, &stats, 5); */

Código: Seleccionar todo

int sceIoIoctl(SceUID fd, unsigned int cmd, void *indata, int inlen, void *outdata, int outlen);
/*Permite la comunicación con un dispositivo más allá de lectura y escritura. (control de i/o)
@parámetro fd – Dispositivo al que se va a hacer el ioctl.
@parámetro cmd – Comando a enviar
@parámetro *indata – Bloque de datos a enviar, en otro caso es nulo (NULL)
@parámetro inlen – Longitud de indata, si es nulo, será 0.
@parámetro *outdata – Bloque de datos a recibir, en otro caso será nulo (NULL)
@parámetro outlen – Longitud de outdata, si es nulo, será 0.
Ejemplo: sceIoIoctl(fd, 0x02425818, &bufferin, sizeof(bufferin), 0, 0); */

Código: Seleccionar todo

int sceIoIoctlAsync(SceUID fd, unsigned int cmd, void *indata, int inlen, void *outdata, int outlen);
/*Permite la comunicación con un dispositivo más allá de lectura y escritura. (control de i/o), todo con asincronía.
@parámetro fd – Dispositivo al que se va a hacer el ioctl.
@parámetro cmd – Comando a enviar
@parámetro *indata – Bloque de datos a enviar, en otro caso es nulo (NULL)
@parámetro inlen – Longitud de indata, si es nulo, será 0.
@parámetro *outdata – Bloque de datos a recibir, en otro caso será nulo (NULL)
@parámetro outlen – Longitud de outdata, si es nulo, será 0.
Ejemplo:
sceIoIoctlAsync(fd, 0x02425818, &bufferin, sizeof(bufferin), 0, 0); */

Código: Seleccionar todo

int sceIoSync(const char *device, unsigned int unk);
/* Sincroniza el dato de un dispositivo dado.
@parámetro *device – Dispositivo iniciado.
@parámetro unk – Desconocido, usualmente 0.
Ejemplo: sceIoSync(“ms0://”, 0); */

Código: Seleccionar todo

int sceIoWaitAsync(SceUID fd, SceInt64 *res);
/* Dispone una espera hasta que toda asincronización se complete.
@parámetro fd – Descriptor en asincronía.
@parámetro *res – Resultado.
Ejemplo: SceInt64 res;
sceIoWaitAsync(fd, &res); */

Código: Seleccionar todo

int sceIoWaitAsyncCB(SceUID fd, SceInt64 *res);
/* Dispone una espera hasta que toda asincronización se complete, con una serie de callbacks.
@parámetro fd – Descriptor en asincronía.
@parámetro *res – Resultado.
Ejemplo: SceInt64 res;
sceIoWaitAsyncCB(fd, &res); */

Código: Seleccionar todo

int sceIoPollAsync(SceUID fd, SceInt64 *res);
/* Llama a que se complete la asincronía.
@parámetro fd – Descriptor en uso con asincronía.
@parámetro *res – Resultado.
Ejemplo: sceIoPollAsync(fd, &res); */

Código: Seleccionar todo

int sceIoGetAsyncStat(SceUID fd, int poll, SceInt64 *res);
/* Devuelve el estado de si está o no completa la asincronía.
@parámetro fd – Descriptor en uso con asincronía.
@parámetro poll – En el caso de ser 0, espera a que devuelva su estatus, en otro caso hace un poll a fd.
@parámetro *res – Resultado.
Ejemplo: sceIoGetAsyncStat(fd, 0, &res); */

Código: Seleccionar todo

int sceIoCancel(SceUID fd);
/* Cancela la asincronía de un descriptor.
@parámetro fd – Descriptor en uso con asincronía.
Ejemplo: sceIoCancel(fd); */

Código: Seleccionar todo

int sceIoGetDevType(SceUID fd);
/* Devuelve el tipo de dispositivo del descriptor analizado.
@parámetro fd – Descriptor en uso.
Ejemplo: sceIoGetDevType(fd); */

Código: Seleccionar todo

int sceIoChangeAsyncPriority(SceUID fd, int pri);
/* Cambia la prioridad del proceso de asincronía de un descriptor dado.
@parámetro fd – Descriptor dado.
@parámetro pri – Prioridad.
Ejemplo: sceIoChangeAsyncPriority(fd, 0x10); */

Código: Seleccionar todo

int sceIoSetAsyncCallback(SceUID fd, SceUID cb, void *argp);
/* Determina un callback para la asincronía del descriptor en cuestión.
@parámetro fd – Descriptor en asincronía.
@parámetro cb – Callback creado con sceKernelCreateCallback
@parámetro *argp – Puntero al argumento para pasar al CB.
Ejemplo: int cb;
cb = sceKernelCreateCallback(“Callback”, call, NULL);
(…)
sceIoSetAsyncCallback(fd, cb, NULL); */


Dando, de esta manera, también por terminado a la librería de I/O.



... To be continued :katana:


Este es un documento que NO está terminado. De dicha manera, es posible que haya errores, faltas ortográficas, malformaciones genéticas, o pornografía subliminal. :chapao:

Si encuentras algún error que deba corregirse, o quieres que se añada algo en especial, comunícalo mediante este mismo hilo. Podéis ver lo que se está pensado añadir en el propio índice, de manera que se tenga en cuenta para futuras peticiones.
No tiene los permisos requeridos para ver los archivos adjuntos a este mensaje.
:katana:
<MrTuto_Alek> todos vosotros, hermanos, a mi lado siempre tendreis un trozo de carne para llevaros a la boca :)

Avatar de Usuario
fidelcastro
Moderador Global
Moderador Global
Mensajes: 2471
Registrado: 04 Sep 2009, 18:49

Re: [Manual] Programación en C para PSP

Mensaje por fidelcastro »

Magnifico, como siempre Alek, gran trabajo :oki:
Imagen

La verdad os hará libres (Juan 8:32). Y la mentira creyentes.

Avatar de Usuario
dark_sasuke
Moderador Global
Moderador Global
Mensajes: 3379
Registrado: 03 Sep 2009, 02:13
Twitter: D4rkyt0

Re: [Manual] Programación en C para PSP

Mensaje por dark_sasuke »

Muy bueno Alek!!! :oki:

Alek escribió:malformaciones genéticas, o pornografía subliminal.



:juasjuas: :juasjuas: :juasjuas: :juasjuas:
Imagen

Avatar de Usuario
finfantasy
Habitual
Habitual
Mensajes: 153
Registrado: 15 Oct 2009, 19:00

Re: [Manual] Programación en C para PSP

Mensaje por finfantasy »

vendrá bien para echarle un vistazo de vez en cuando :)

Avatar de Usuario
Robione22
Desarrollador
Desarrollador
Mensajes: 25
Registrado: 07 Dic 2009, 19:25
PSN ID: robione202
Ubicación: México
Contactar:

Re: [Manual] Programación en C para PSP

Mensaje por Robione22 »

Muy buen manual :D

Este si me va bien jejeje, pero estoy atorado como siempre

Todo va bien, hasta el make, pero al teclear make install me da esto:

Código: Seleccionar todo

robione22@robione22:~/psp/zlib$ make install
Installing libz into /usr/local/pspdev/psp
cp: no se puede crear el fichero regular «/usr/local/pspdev/psp/include/zlib.h»: Permiso denegado
cp: no se puede crear el fichero regular «/usr/local/pspdev/psp/include/zconf.h»: Permiso denegado
make: *** [install] Error 1
robione22@robione22:~/psp/zlib$ sudo make install
make: psp-config: No se encontró el programa
Makefile:9: /lib/build.mak: No existe el fichero ó directorio
make: *** No hay ninguna regla para construir el objetivo `/lib/build.mak'.  Alto.


Como me dijo de los permisos lo hice con sudo, y en la terminal en modo root me dice lo mismo del segundo error
¿Cómo será el amor en el futuro?
Spoiler:

Código: Seleccionar todo

robione22@robione22:~$ sudo chown tu micorazon
:adora:

Avatar de Usuario
pspCaracas
Moderador Global
Moderador Global
Mensajes: 3080
Registrado: 03 Sep 2009, 03:29
Ubicación: Buenos Aire - Argentina
Contactar:

Re: [Manual] Programación en C para PSP

Mensaje por pspCaracas »

Está muy bien para el que desea meterse en la programación de homebrews usando C...gracias Alek!! :oki: :oki: :oki: :oki:
http://farm3.static.flickr.com/2497/3983880148_f5ae0aaab2_o.png

Avatar de Usuario
m0skit0
Administrador
Administrador
Mensajes: 5585
Registrado: 03 Sep 2009, 09:35
Ubicación: 0xdeadbeef

Re: [Manual] Programación en C para PSP

Mensaje por m0skit0 »

Mr. Tuto is back!

Pero como en los anteriores tutos, o sabes ya C, o mamas :lol:
Imagen

Avatar de Usuario
Alek
ViP Hordes
ViP Hordes
Mensajes: 89
Registrado: 19 May 2010, 19:16
PSN ID: PlayAlek
Contactar:

Re: [Manual] Programación en C para PSP

Mensaje por Alek »

Robione22 escribió:Muy buen manual :D

Este si me va bien jejeje, pero estoy atorado como siempre

Todo va bien, hasta el make, pero al teclear make install me da esto:

Código: Seleccionar todo

robione22@robione22:~/psp/zlib$ make install
Installing libz into /usr/local/pspdev/psp
cp: no se puede crear el fichero regular «/usr/local/pspdev/psp/include/zlib.h»: Permiso denegado
cp: no se puede crear el fichero regular «/usr/local/pspdev/psp/include/zconf.h»: Permiso denegado
make: *** [install] Error 1
robione22@robione22:~/psp/zlib$ sudo make install
make: psp-config: No se encontró el programa
Makefile:9: /lib/build.mak: No existe el fichero ó directorio
make: *** No hay ninguna regla para construir el objetivo `/lib/build.mak'.  Alto.


Como me dijo de los permisos lo hice con sudo, y en la terminal en modo root me dice lo mismo del segundo error


Supongo que ya habrás hecho eso de

Código: Seleccionar todo

alex@Hesperia:~/psp/trunk/zlib$ sudo chmod a+rwx /usr/local/pspdev/psp/*
, de manera que asigna permisos a las carpetas redundantes anteriores (pspdev, psp, etc) y vete probando con ese mismo install.

Si eso no lo soluciona, haz un chown para tu usuario y tener la "propiedad" de la carpeta /pspdev/ y comprueba que todos los permisos estén asignados correctamente.
:katana:
<MrTuto_Alek> todos vosotros, hermanos, a mi lado siempre tendreis un trozo de carne para llevaros a la boca :)

Avatar de Usuario
Dark_Miguel
Desarrollador
Desarrollador
Mensajes: 63
Registrado: 12 May 2010, 22:26
PSN ID: Ninguna, pronto me creo una....
Ubicación: Spain, Andalucía. Jaén
Contactar:

Re: [Manual] Programación en C para PSP

Mensaje por Dark_Miguel »

Muchas gracias!! Muy bueno, espero con impaciencia el uso de VLF.
Imagen

Avatar de Usuario
guitripio
Habitual
Habitual
Mensajes: 160
Registrado: 17 Nov 2009, 14:41
Ubicación: Somewhere...!!!

Re: [Manual] Programación en C para PSP

Mensaje por guitripio »

cual de los 2, O.S. es mas facil para hacer todo esto...?

Win ó Linux...?
o cual sistema, es mas recomendable,para poder hacer todo lo de este, tuto...?
Imagen Imagen Imagen

Responder