PDA

Ver la versión completa : Problema con SDK de Mirko



Puck2099
19/10/2004, 23:29
Hola,

Estoy usando el SDK de Mr. Mirko bajo Linux para "portar" el código hecho con el SDK oficial de lo que llevaba de mi remake del "Lady Killer" y me han surgido unos problemillas.

Quiero hacer una copia del framebuffer actual para, después de pintar unos sprites en el framebuffer, poder "restaurar" zonas de la pantalla con un sprite que hay de fondo guardado en la copia.

Pues bien, el framebuffer temporal lo he definido como:

u16 frametemp[320*240];

Mi problema llega cuando hago por ejemplo esto:

for (index=0; index<320*240;index++) frametemp[index] = framebuffer[nflip][index];
Al ejecutarlo en la GP32 se queda la consola colgada sin llegar a mostrar nada a partir de esa línea.

A lo mejor es una tontería, pero no veo como arreglarlo.

Otra cosilla. He probado a poner la pantalla en modo 16 bits y mostrar 2 sprites, uno que ocupa toda la pantalla y otro que ocupará un 80%. A 66 Mhz, con mostrar esos dos sprites y unas líneas de código nada "pesadas" (unos ifs) la consola no pasa de 20 FPS. ¿Es normal que sea tan lenta su ejecución?, ¿cómo de rápida sería comparativamente usando 8 bits?. Es que con el programa mucho más complejo en 8 bits usando el SDK oficial conseguía más de 100 FPS (y creo que más de 500, pero no me acuerdo).

Muchas gracias por la ayuda.

Puck2099
20/10/2004, 20:24
¿Nadie tiene alguna idea de lo que puede pasar?, alguna pistilla aunque sea...

Saludos

zano
20/10/2004, 21:32
No se si sera (he hecho un par de chorraditas para la gp32) pero q tipo de variable es index? quizá se te queda corto para 320*240 movimientos.

Un saludo.

Pd:El framebuffer esta definido como u16 framebuffer[2][320*240] supongo no?.

Puck2099
20/10/2004, 22:22
No se si sera (he hecho un par de chorraditas para la gp32) pero q tipo de variable es index? quizá se te queda corto para 320*240 movimientos.

Hostias, pues es verdad. La variable index es un int que, ahora que lo pienso, está definido de -32000 (más o menos) a 32000, y mi variable alcanza valores del orden de 70000.

A ver si lo pruebo y te digo.


Pd:El framebuffer esta definido como u16 framebuffer[2][320*240] supongo no?.

Pues el framebuffer está definido como un vector de dos punteros a unas posiciones de memoria definidas de la GP32.

Saludos

Puck2099
20/10/2004, 23:57
Bueno, pues he probado a cambiar la declaración del "index" de int a long y sigue ocurriendo lo mismo :(

¿Alguna idea?. Podría hacer lo que quiero de otro modo, pero me complicaría muchísimo más el tema gráfico además de "engordar" el fichero con imágenes que de este modo me ahorraría.

Saludos

theNestruo
21/10/2004, 03:05
En vez de contar hasta 320*240, anida dos cuentas: una hasta 320 y otra hasta 240. Y en vez de acceder a los arrays mediante un índice, comos lo haces de forma lineal, utiliza cursores:


int row, column; /* Contadores */
u16 *ptrTemp, *ptrBuffer; /* Cursores */

for (ptrTemp=fametemp, ptrBuffer=framebuffer[nflip], row=0; row<240; ++row)
for (column=0; column<320; ++ptrTemp, ++ptrBuffer, ++column)
(*ptrTemp)=(*ptrBuffer);

Nota: no te aseguro que el código esté correcto, pero me imagino que pillas la idea.
Te pongo otra versión un poco más legible por si no estás acostumbrado a hacer cosas "raras" con los for.


int row, column; /* Contadores */
u16 *ptrTemp, *ptrBuffer; /* Cursores */

ptrTemp=frametemp;
ptrBuffer=framebuffer[nflip];

for (row=0; row<240; ++row)
for (column=0; column<320; ++column) {
(*ptrTemp)=(*ptrBuffer);
++ptrTemp;
++ptrBuffer;
}

Mergos
21/10/2004, 09:37
Prueba con memcpy o utiliza una transferencia DMA.

theNestruo
21/10/2004, 12:57
Mergos: Leñe, ¡es verdad! Me obsesioné tanto con solucionar el problema del cuelgue del código de Puck2099 que no se me ocurrió lo del memcpy()... (Nota personal: hay que dormir más, que luego pasan estas cosas)

Puck2099: Te adjunto el código utilizando memcpy():


memcpy (framebuffer[nflip], frametemp, sizeof (u16) * 320 * 240);

Puck2099
21/10/2004, 17:58
Muchas gracias a los dos, en cuanto llegue a casa (estoy en la universidad) lo pruebo a ver si se arregla.

Por cierto, para el caso opuesto, es decir, restaurar "cuadrados" de datos del frametemp al framebuffer, ¿habría que hacerlo como lo puse yo con un índice o hay alguna forma de copiar directamente del frametemp a memoria como con el memcpy?

Gracias de nuevo

theNestruo
21/10/2004, 18:13
Podrías utilizar memcpy(), pero sólo con los bloques consecutivos de píxeles. Por ejemplo, si tienes que restaurar un bloque de 48x48 píxeles, tendrías que hacer 48 llamadas a memcpy(), y copiar cada vez 96 bytes (48 píxeles x 2 Bpp). También se puede hacer modificando el código que puse yo mediante punteros cursores, pero será más lento que usando memcpy() casi seguro.

Puck2099
22/10/2004, 00:12
Hola,

He probado el código que me has puesto del memcpy, theNestruo, y, aunque ya no se queda colgado, parece que lo que hace es corromper el framebuffer.

He mirado por Internet y he visto una función memcpy (no sé si es la que tú me indicabas) definida por:

void* memcpy (void *out, const void *in, size_t n);
Según eso los argumentos son al reves de lo que tú me indicas, ¿no?. Cambiándolos de posición se sigue quedando colgada :(

¿Puede ser por la declaración del frametemp?, ¿tendría que reservar memoria y declararlo mejor como un puntero?

Muchas gracias por la ayuda, poco a poco voy avanzando en mis proyectos.

Puck2099
22/10/2004, 00:19
Uhm, creo que lo he arreglado reservando memoria con malloc y definiendo frametemp como un puntero.

A ver si hago unas pruebas y os cuento...

Saludos

Puck2099
22/10/2004, 00:25
Efectivamente, ya funciona :)

Muchas gracias por lo de la función memcpy, yo ni sabía que existía :D

Saludos

theNestruo
22/10/2004, 00:54
Escrito originalmente por Puck2099
Según eso los argumentos son al reves de lo que tú me indicas, ¿no?.
Tienes razón... en parte. :) Lo que pasa es que estoy acostumbrado a la idea de "volcar" el búfer posterior en el búfer frontal (el visible), y por eso me hice un lío con las variables (estaba casi seguro de que lo que había que hacer era copiar de frametemp a framebuffer[nflip].

P.S.I:
Lo de copiar "cuadraditos" sólo, ¿cómo lo llevas?

P.S.II:
Tu idea de dibujar los sprites y luego restaurar el fondo está bien, pero vamos a ver si esto funciona mejor (por lo menos más sencillo creo que sí que es):
framebuffer[0] y framebuffer[1] son los búferes frontal (visible) y posterior (oculto) de la pantalla, y habrá alguna llamada para alternarlos, ¿no? (si no es así, casi nada de lo que voy a decir a continuación tiene sentido). Si almacenas el fondo sin sprites en frametemp, para cada frame vuelcas el contenido de frametemp en el búfer oculto (framebuffer[0] o framebuffer[1], dependiendo del caso). Dibujas los sprite sobre ese búfer oculto y luego alternas los búferes.
De esta forma te olvidas de llevar el control de qué zonas tienes que restaurar y todo eso (es el sistema que utilizaba yo en mi Rick Dangerous para Windows, con la diferencia de que mi "frametemp" era gigantesco -contenía la pantalla actual entera de arriba a abajo-).

Puck2099
22/10/2004, 09:33
(estaba casi seguro de que lo que había que hacer era copiar de frametemp a framebuffer[nflip].

Sí, eso también tengo que hacerlo que hacerlo para restaurar los "cuadraditos".


Lo de copiar "cuadraditos" sólo, ¿cómo lo llevas?

Pues lo he probado con un "cuadrado gigante", empezando desde la dirección apuntada por frametemp hasta la mitad de la pantalla más o menos y funciona bien. Supongo que para los pequeños solo tendré que hacer un duplicado del puntero frametemp y situarlo al principio de los datos que quiera restaurar, restaurarlos y volverlo a situar, etc.


Tu idea de dibujar los sprites y luego restaurar el fondo está bien, pero vamos a ver si esto funciona mejor (por lo menos más sencillo creo que sí que es):
framebuffer[0] y framebuffer[1] son los búferes frontal (visible) y posterior (oculto) de la pantalla, y habrá alguna llamada para alternarlos, ¿no? (si no es así, casi nada de lo que voy a decir a continuación tiene sentido). Si almacenas el fondo sin sprites en frametemp, para cada frame vuelcas el contenido de frametemp en el búfer oculto (framebuffer[0] o framebuffer[1], dependiendo del caso). Dibujas los sprite sobre ese búfer oculto y luego alternas los búferes.
De esta forma te olvidas de llevar el control de qué zonas tienes que restaurar y todo eso (es el sistema que utilizaba yo en mi Rick Dangerous para Windows, con la diferencia de que mi "frametemp" era gigantesco -contenía la pantalla actual entera de arriba a abajo-).

Sí, utilizo los framebuffer[0] y framebuffer[1] para hacer un "doble buffering" dibujando en el búfer oculto y, cuando está todo dibujado, hago oculto el visible y visible el oculto.

Voy a explicar como va lo de los cuadritos, el frametemp, etc. para que se entienda mejor:

Primo se dibuja un sprite de fondo en el búfer oculto, una chica "maja", entonces hago copia del búfer oculto en frametemp para guardar ese frame. Después se dibuja sobre ese fondo otro que solo lleva la silueta de la chica, ocultando el contenido. Pues bien, el jugador puede "voltear" baldosas de la silueta que permitirían ver a la chica de debajo una vez dadas la vuelta.

Esas baldosas son mis "cuadraditos", una vez esté volteada la baldosa, restauraría el trozo de fondo correspondiente desde frametemp al frame oculto. Luego se pintan los enemigos y personaje y se hace visible el fondo oculto, ocultando el visible y vuelta a empezar.

Espero haberme explicado bien, lo de usar el frametemp y restaurar me pareció la solución más cómoda a lo de las "baldosas", pero si se os ocurre algo mejor será bien recibido ;)

Saludos