FAQ de programación
De Wiki GP32Spain, la enciclopedia libre.
¿Que lenguajes de programación soporta GP2X?
Se puede programar para la GP2X en C, C++, en Fenix y en Python (Gracias al interprete PyGame). Además, es posible hacer uso de las librerías SDL y GP2X Minimal Library SDK de Rlyeh.
Cómo volver al menú principal de la consola al salir de una aplicación programada en C/C++
Basta con añadir las siguientes instrucciones al final del código, justo antes de salir de la aplicación:
chdir("/usr/gp2x");
execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL);
Puesto que execl() está en unistd.h, será necesario añadir
#include <unistd.h>
Por ejemplo,
#include <unistd.h>
- int main (int argc, char** argv)
{
.
. <FUNCIONALIDAD DE LA APLICACIÓN>
.
chdir("/usr/gp2x");
execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL);
return 0;
}
Cómo hacer una aplicación compatible con la salida de TV
El tamaño de la salida a pantalla (LCD o TV) está controlado por tres registros de la memoria:
- C000 2906 - Escala horizontal de la pantalla
- C000 2908 - Escala vertical de la pantalla
- C000 290C - Anchura de la pantalla
El area visualizable de la pantalla está controlado por los registros de ventanas RGB:
- C000 0x28E2 + window*8 - Coordenada X1 de la ventana número (window+1)
- C000 0x28E4 + window*8 - Coordenada X2 de la ventana número (window+1)
- C000 0x28E6 + window*8 - Coordenada Y1 de la ventana número (window+1)
- C000 0x28E8 + window*8 - Coordenada Y2 de la ventana número (window+1)
Donde window puede variar de 0 a 3.
Los valores que se deben aplicar a estos registros dependen de que la pantalla esté en LCD, en TV-Out PAL o en TV-Out NTSC. El método para calcularlo es el siguiente:
- Comprobamos si el TV-Out está activado, para ello se debe cumplir que el valor del registro C000 2800 tenga el bit 17 con valor 1.
- Miramos el tamaño real de la pantalla. Para ello comprobar el valor del registro C000 2818 (altura real de la pantalla). Si el valor es 239, estamos en LCD. Si el valor es 287, estamos en TV PAL. Si el valor es 231, estamos en TV NTSC.
- Tomamos la dimension X de nuestra imagen a representar, y aplicamos este calculo: dimensionX/320*MaxX donde MaxX es 1024 si estamos en LCD o 489 Si estamos en TV. El resultado lo ponemos en el registro C000 2906
- Tomamos la dimension Y de nuestra imagen a representar, y aplicamos este calculo: dimensionY/240*MaxY*BitsPP donde BistPP es 1 para 8 bits y 2 para 16 bits de color. MaxY es 320 si estamos en LCD, 274 Si estamos en TV PAL o 331 si estamos en TV NTSC. El resultado lo aplicamos en el registro C000 2908.
- Nos aseguramos de que el valor en el registro C000 290C es 320*BitsPP
- Finalmente, escalamos las ventanas RGB teniendo en cuenta que sus coordenadas deben tener un ancho maximo de 329 para LCD o de 669 para TV, así como un alto máximo de 239 para LCD, de 279 para TV PAL o de 231 para TV NTSC
Cómo calcular los FPS
Pseudocódigo:
num_frames=0
tiempo=tiempoActual()
.
.
.
mientras (...) <-- bucle principal de la aplicación
{
num_frames=num_frames+1;
si (tiempoActual()-tiempo >= 1 segundo)
{
FPS=num_frames
muestra(FPS)
num_frames=0
}
.
. <FUNCIONALIDAD DE LA APLICACIÓN>
.
}
Escritura de ficheros en modo síncrono desde C/C++
El Linux de GP2X accede a disco en modo asíncrono por defecto. Es decir, si por ejemplo una aplicación decide escribir algo a disco, en realidad se escribe en un buffer, y Linux decide cuándo lo pasa realmente a disco. Esto puede provocar que ciertas operaciones de escritura no se realicen si, por ejemplo, apagamos la consola con la aplicación abierta y Linux aún no ha volcado el contenido del buffer en disco.
Pues bien, a parte de la posibilidad de crear un script que fuerce este modo de escritura, tal como se explica en este tutorial (ver apartado 1.4), se pueden conseguir los mismos resultados también desde C ejecutando la instrucción sync() después de una llamada a fclose():
FILE* archivo = fopen(...); fwrite(...); fclose(archivo); sync();
Puesto que sync() está en unistd.h, será necesario añadir
#include <unistd.h>
Cómo obtener la lista de ficheros de un directorio en C/C++
Mediante la función scandir() de dirent.h. Ejemplo:
#include <stdio.h>
#include <dirent.h>
int main(int argc, char** argv)
{
int n, i;
struct dirent **namelist; // Vector de elementos del tipo dirent. Esta estructura almacena el nombre del fichero.
// Obtención de la lista de ficheros (n contiene el número de ficheros)
n=scandir(".",&namelist,NULL,NULL);
// Recorrido por la lista
i=0;
while(i<n)
{
printf("%s\n", namelist[i]->d_name);
i++;
}
//Libera memoria
i=0;
while(i<n)
{
free(namelist[i]);
i++;
}
return 0;
}
