El tema de los gráficos de cada juego, va así, mas o menos:
Antiguamente: grid de 4x3, por lo que es necesario cargar hasta 12 texturas. Cada textura puede medir un máximo de 1024 x 1024 a 32 bits, por lo que ocupa 4MB (y en total, 48 MB).
Justo después de esas entradas, al final de la memoria de textura, se reserva el espacio para la imagen de fondo del juego, puesto que es la mas grande (1920x1080 a 32 bits, pero si es mas grande, tenemos espacio suficiente). Tened en cuenta que aquí no estamos hablando de otras texturas que usa el programa, ni de los caracteres TTF, solo de la imagen de los juegos (el ICON0.PNG o la carátula) pero ya tenemos una limitación con respecto a las imágenes que podemos representar.
Lo nuevo: ahora soportamos hasta 32 texturas, aunque el máximo que usa el grid es 30 (6x5), nuevamente de 1024 x 1024 32 bits, por lo que en total, gastamos 128 MB, la mitad de la memoria gráfica disponible, solo para poder alojar esas imágenes.
La textura 32 (BIG_PICT) se corresponde con la imagen de fondo del juego, mientras que la 33 sería la imagen de fondo personalizable (por ejemplo PICT0.JPG). Curiosamente, la textura 33 se aloja antes que la 32, pues le reservamos un espacio fijo de 2048 x 1200 y 32 bits, mientras que prefiero dejar espacio indefinido para la del juego
Pero, ¿como se cargan estas imágenes?. La procedencia es PNG o JPG y eso se hace con la ayuda de dos funciones gemelas, que permiten cargar desde fichero o desde memoria, el JPG o el PNG, usando la misma estructura que he descrito y dejando almacenado en varios arrays los datos necesarios para su utilización como textura.
En primer lugar, el inicio de las texturas de este tipo, lo marca
png_texture (ver main.h)
Las funciones de carga son:
int LoadTexturePNG(char * filename, int index);
int LoadTextureJPG(char * filename, int index);
Si filename es NULL, se usarán los datos de la estructura
my_png_datas para descomprimir el PNG o JPG desde memoria. Este es el caso de por ejemplo, las imágenes que se extraen de una ISO de PS3, que no pueden leerse vía sistema de archivos de la PS3. Si no es NULL, contiene la ruta donde está la imagen.
index, antiguamente era de 0 a 11 para las imagenes normales y 12 para la de fondo, grandota. Ahora el rango es de 0 a 31, siendo 32 (BIG_PICT) la de fondo grandota y 33 (BIG_PICT + 1) la del fondo customizable.
A la vuelta si hubo error devuelve valor negativo, pero hay que tener en cuenta que no en todos los casos se devuelve error (si la imagen es demasiado grande, simplemente, se pone una imagen por defecto para cubrir la eventualidad).
Como hemos visto,
my_png_datas se usa de forma interna para trabajar y de esa forma, es posible usarla de forma especial para cargar de memoria. Existe un array de índices que determina la posición real de la textura para cada valor de
index como parámetro de entrada a estas funciones. Esto que no sería necesario para cargar desde un modo GRID, resulta necesario en el modo Coverflow, debido a que no hacerlo así, deberíamos ir desplazando cada textura desde memoria, lo cual sería lentísimo.
Pongamos el siguiente caso, tenemos una textura cargada como índice 12 en la posición de memoria 12, pero después de un desplazamiento, resulta que el índice correspondiente es el 11, pero la posición sigue siendo la 12... por lo que tenemos dos opciones:
- O corremos de posición todas las texturas (4MB cada una...) para que se corresponda con los índices.
- O creamos un array que actúa de traductor de forma que en el índice 11 de ese array, se señale a la posición 12 de memoria y simplemente, nos dedicamos a actualizar las posiciones en esa tabla, de forma rotatoria, cuando corresponda.
Este último caso es el nuestro y es de lo que se encarga
int Png_index[BIG_PICT + 2];, que ya deben estar ajustadas antes de llamar a esas dos funciones. Los índices BIG_PICT u BIG_PICT + 1, no son afectados por esa tabla, por cierto (aunque tenga espacio para tratarlos).
Bien, a la salida de esas funciones, tenemos una serie de datos en:
PngDatas Png_datas[BIG_PICT + 2]; // datos como el ancho y alto de la textura, se almacenan aquí.
u32 Png_offset[BIG_PICT + 2]; // offset de la textura en el RSX o 0, si no está cargada
Para seleccionar la textura, haríamos luego (este ejemplo es el que carga la imagen de fondo personalizable):
if(Png_offset[BIG_PICT + 1]) { // esta cargada la textura?
int i = BIG_PICT + 1;
tiny3d_SetTextureWrap(0, Png_offset[i], Png_datas[i].width,
Png_datas[i].height, Png_datas[i].wpitch,
TINY3D_TEX_FORMAT_A8R8G8B8, TEXTWRAP_CLAMP, TEXTWRAP_CLAMP,1);
DrawTextBox(-1, -1, 1000, 850, 514, (background_sel & 1) ? 0xffffffff : 0xcfcfcfff);
return;
}
Y este es el sistema que utilizan TODAS las texturas: comprobar que offset no sea 0, ajustar datos de textura y visualizar.
Complementariamente a estas, para la visualización de imágenes, tenemos:
int Png_iscover[BIG_PICT + 2];
Esto contiene una serie de valores para determinar si la textura cargada es cover o no y ajustar el modo de visualización que creamos apropiado (caratula vertical u horizontal, etc).
---
La carga de imágenes de los juegos se hace en segundo plano. Para ello, necesitamos conectar las funciones necesarias al hilo que trabaja en segundo plano (por economía y para evitar colisiones, se utiliza un solo hilo "programable") e inicializar valores.
get_games() (main.c) se encarga de inicializar los valores necesarios para todas las imágenes que vamos a cargar de los juegos, aunque en el modo Coverflow se pueden hacer ajustes individuales.
Como vemos dentro, la función
get_games_2() es conectada como evento al hilo de segundo plano y si le echáis un ojo, podéis ver como se cargan las imágenes teniendo en cuenta la prioridad por dispositivo y si es un favorito o no, desde la posición
int_currentdir, que es la copia interna de
currentdir, el índice a la tabla que contiene los datos de los juegos (se usa una copia interna por que estamos en segundo plano... y si en primer plano cambiamos el valor, crearíamos incongruencia en los datos que estamos cargando). Por cierto, usamos índices a "directorios", por que los juegos jailbreak se almacenan en directorios dentro de una carpeta, como "GAMES" o "GAMEZ" y la lista, realmente, contiene estos directorios mas otros datos de interés (como la ID de los juegos, el flag de dispositivo y de tipo de juego, etc). Si queréis ver estos datos, mirad en utils.h, las estructuras
t_directories y
entry_favourites, para la lista de favoritos (donde el index apunta a una entrada directories[], del juego o contiene un número negativo si no apunta a ninguno). Tambien echadle un ojo a:
extern int ndirectories; // total de juegos
extern t_directories directories[MAX_DIRECTORIES]; // lista con los datos de los juegos
Volviendo a la función de antes, podemos ver
get_icon():
int get_icon(char * path, const int num_dir)
El path es la variable donde se copiara la ruta de la imagen encontrada, siendo num_dir el indice al juego. Según el retorno de esta función, se ajusta
Png_iscover[], de la que ya hemos hablado antes y que luego es utilizada en
draw_gui1() y draw_gui2() para mostrar de forma apropiada caratulas, iconos o lo que sea.
Esto poco mas o menos os orienta un poco de como funcionan las cosas. Es importante que los favoritos tengan al menos, tantas entradas como juegos se muestran en pantalla. En Iris Manager hay dos listas de favoritas: una referente a Homebrew/PSN y otra referente a los demás juegos, pero ambas entroncan en una misma lista común, que antes era de tipo
tfavourites (ver utils.h) con 12 entradas y ahora es de tipo
tfavourites2, con 32 entradas (por lo que cubre de sobra los hasta 6 X 5 juegos del modo GRID máximo)
la tabla común de favoritos es:
tfavourites2 favourites;
Y se comparte mediante el uso de las funciones:
void GetFavourites(int mode);
void SetFavourites(int mode);
El tamaño de la tabla de favoritos es uno de los límites a 32 juegos, obviamente, pero los otros límites son los arrays que he estado describiendo y los espacios reservados para textura.
Eso aparte de como se maneje el grid y de las funciones inicializadoras y de ajuste, y mil cosas mas, por lo que si el plan es explicaros un poco como funciona por encima y señalar algunos puntos clave y vosotros os buscáis la vida, vale, pero no puedo llegar a más y si vosotros tampoco, es más fácil que lo haga yo mismo que intentar abarcarlo en un comentario

(son muchos pequeños detalles por todas partes: tantos que incluso yo puedo olvidar alguno con la diferencia de que cuando surja un problema, sabré donde está el fallo a posteriori, pero estamos como cuando vas al diccionario para consultar una palabra y te lo explican con palabras que tampoco entiendes... un lío en ese caso
![más risas [+risas]](/images/smilies/nuevos/risa_ani3.gif)
)
Saludos