Iniciar sesión

Ver la versión completa : Reinicios al pintar sprite :(



Puck2099
11/04/2005, 15:28
Hola,

Visto que mi Lady Killer daba ciertos problemas con las BLU+ me puse a hacer unas pruebas para optimizar un poco más la velocidad del juego y ver si así funciona. Efectivamente, los problemas que parecían debidos a refrescos de pantalla desaparecen con estas optimizaciones, pero sin embargo me he encontrado con que la consola se reinicia al ejecutar dicha función.

Lo raro es que no siempre se reinicia, osea, con el mismo fxe, grabado en la misma smc y metida en la misma GP32, un día funciona y al día siguiente se reinicia a llegar la ejecución a dicha función.

Los reinicios siempre me han dado por problemas con memoria, punteros mal puestos y cosas así, pero es que he cambiado una trivialidad por otra y sigue igual.

Paso a explicaros los cambios:

Tengo incluída una imagen de 320x240 llamado "maq_chica.h" de 8 bits y convertida a .h con el gp32converter. Bien, asigno a un puntero esa imagen:

unsigned char * immarco;
immarco = (unsigned char *) marq_chica;


El problema, cuando se reinicia la consola, viene al pintarlo. Antes lo pintaba con:

GpBitBlt (NULL, &gpDraw[nflip], 0, 0, 320, 240, immarco, 0, 0, 320, 240);
Y funcionaba bien. Entonces comento esa línea y pinto la imagen, pero dejando sin pintar un recuadro interior de 256x192 que pintaré después con otra función.

GpBitBlt (NULL, &gpDraw[nflip], 0, 0, 320, 44, immarco, 0, 0, 320, 240);
GpBitBlt (NULL, &gpDraw[nflip], 0, 236, 320, 4, immarco, 0, 236, 320, 240);
GpBitBlt (NULL, &gpDraw[nflip], 0, 0, 32, 240, immarco, 0, 0, 320, 240);
GpBitBlt (NULL, &gpDraw[nflip], 288, 0, 32, 240, immarco, 288, 0, 320, 240);

Bueno, pues ahora al llegar ahí se reinicia la consola. Lo más curioso del tema es que si por ejemplo comento esas 4 líneas y descomento la original (quedando como al principio) muchas veces sigue el problema del reinicio.

He probado a pasar los fxe con el gplink y un lector de tarjetas, he compilado con el gcc 3.2.1 y gcc 3.4.3 en distintos ordenadores y sigue igual, por lo que solo puedo atribuir el problema al código...

¿Alguna idea para una ayudar a un programador desesperado? :llorosa:

Muchas gracias

oankali
11/04/2005, 16:46
Estas líneas son correctas. Tendrías que poner algo más de código para ver qué puede ser.

Y aún puedes optimizar algo más cambiando las dos últimas líneas por estas:


GpBitBlt (NULL, &gpDraw[nflip], 0, 44, 32, 192, immarco, 0, 44, 320, 240);
GpBitBlt (NULL, &gpDraw[nflip], 288, 44, 32, 192, immarco, 288, 44, 320, 240);


Oankali

Puck2099
11/04/2005, 18:28
Estas líneas son correctas. Tendrías que poner algo más de código para ver qué puede ser.

Y aún puedes optimizar algo más cambiando las dos últimas líneas por estas:


GpBitBlt (NULL, &gpDraw[nflip], 0, 44, 32, 192, immarco, 0, 44, 320, 240);
GpBitBlt (NULL, &gpDraw[nflip], 288, 44, 32, 192, immarco, 288, 44, 320, 240);


Oankali

Hola,

He probado a cambiar mis dos últimas líneas por las tuyas, que efectivamente están más optimizadas (no sé como se me pasó eso), y después de compilarlo ha funcionado perfecto a la primera. He reiniciado varias veces y seguía perfectamente, ya me estaba frotando las manos de alegría y he apagado la consola. A los 10 o 15 minutos, la enciendo, vuelvo a probarlo y se reinicia donde siempre :llorosa:

¿Quieres que te pegue el gpmain.c o te lo mando por mail a ver si ves algo raro?. Lo malo es que el código quizá sea un poco engorroso para alguien que no sea yo :p

Por otro lado, acabo de acordarme que hice otra prueba, cambiando la velocidad de la versión actual del Lady Killer de 133 Mhz a lo que corra por defecto (osea, comenté la línea del cambio de velocidad). Pues bien, ocurre lo mismo, se reiniciaba en el mismo punto cuando lo probaron, mientras que horas más tarde funcionaba bien. A mi me funcionaba bien cuando lo compilé y se lo mandé a quien me lo probó, pero al día siguiente también se me reiniciaba.

Joe, estoy desesperado y solo de pensar que me pase lo mismo en la versión "buena" me da algo...

Saludos

DistWave
11/04/2005, 19:53
Revisa bien todos tus punteros... una de las pegas de C es que es demasiado permisivo a la hora de gestionarlos y muchas veces las cosas funcionan como deberian mientras que otras no por culpa de un puntero, ya que una posicion de memoria sin utilizar no tiene por qué estar a 0, puede tomar cualquier valor.

Otra cosa que debes asegurarte es no utilizar malloc con las SDK oficiales sino gm_malloc, en algunos entornos GCC no funcionan bien las funciones de C nativas.

Saludoss, y si necesitas cualquier cosa aqui estamos ;)

oankali
12/04/2005, 08:12
Estoy de acuerdo con DistWave, probablemente sea un problema de punteros.
Pero hay algo que no cuadra y es que si la función que peta es GpBitBlit(), no veo como un error de punteros puede implicar esa función (salvo si se ha fastidiado la estructura gpDraw), sobretodo si dices que si comentas esas líneas el juego funciona perfectamente.

Envíame el código fuente a 'oankali arroba nekanim punto com' a ver si veo algo sospechoso.

Por cierto, ya que estás optimizando. Por lo visto esta zona que dibujas no cambia nunca, ¿verdad? ¿Has pensado en tenerla preparada al principio en tus dos superfícies para ya no tener que dibujarlas? De esa manera solo te tendrías que preocupar de la parte central. A lo mejor no te sirve porque cambia el cuadro durante el juego.

Oankali.

Puck2099
12/04/2005, 09:14
Como comentais, estoy empezando a creer que es algún problema de punteros.

oankali, ya no estoy tan seguro de que sea la GpBitBlt la que peta, hay veces que he probado a comentarla y sigue fallando igual que a veces dejándolas todas funciona. La depuración con el gcc no es muy buena que digamos, a ver si esta tarde empiezo a meter algunos bucles "pseudoinfinitos" (que se quede ahí hasta que pulse un botón) y puedo localizar el problema.

Si eso te mando esta tarde o mañana el fuente (ahora estoy en el curro) a ver si ves algo sospechoso (anoche pensando en el código vi que perdía punteros cada vez que pasaba de fase, pero en principio, no tendría que afectar en la primera ejecución como pasa ahora).

Respecto a preparar esa zona en las dos superficies, el "marco" no cambia durante las fases, pero se pintan cosas encima (tiempos, vidas, puntos, la cabeza del jugador cuando pasa por encima...). En este caso no se puede hacer lo que dices, ¿verdad?

Muchas gracias a todos :)

oankali
12/04/2005, 10:36
[...]

La depuración con el gcc no es muy buena que digamos, a ver si esta tarde empiezo a meter algunos bucles "pseudoinfinitos" (que se quede ahí hasta que pulse un botón) y puedo localizar el problema.

[...]

No es muy buena no, a menos que tengas el JTAG ese. Por eso ahora mismito estoy preparando un tutorial para instalar el SDK para Windows para poder depurar con VC++6.




[...]

Respecto a preparar esa zona en las dos superficies, el "marco" no cambia durante las fases, pero se pintan cosas encima (tiempos, vidas, puntos, la cabeza del jugador cuando pasa por encima...). En este caso no se puede hacer lo que dices, ¿verdad?

En ese caso no.

Puck2099
12/04/2005, 11:10
No es muy buena no, a menos que tengas el JTAG ese. Por eso ahora mismito estoy preparando un tutorial para instalar el SDK para Windows para poder depurar con VC++6.

Yo empecé con el VC++ en Windows y luego me pasé a Linux. Ayer intenté compilar mi juego en el VC++ para usar el debugger, usé un template de los que usaba antes pero me empezó a dar errores en cosas que con el gcc iban perfectas (como hacer declaraciones del tipo "int numero = 3" dentro de un if). Moviendo esas variables como globales me compilaba, pero luego me empezó a dar errores con las imágenes incluídas como .h diciendo que sobrepasaba la cima del montículo o algo así...

Saludos

Franxis
12/04/2005, 11:12
Te recomiendo que partas el gráfico "inmarco" en varios.

Los reseteos pueden deberse a que los GpBitBlt() que estas utilizando tienen
parámetros de coordenadas que no son múltiplos de 4, con lo cual si haces
acceso a memoria no alineado en enteros (4 bytes) -> reinicio de la consola.
También a que GpBitBlt() haga con los parámetros que le pasas accesos a memoria inválidos (no alineados en direcciones de memoria múltiplos de 4).
Por ello a veces te pasa y a veces no, dependiendo de dónde quede en memoria el gráfico en cuestión (depende de la gp32 dónde le dé por colocar
en memoria el gráfico).

Si partes el gráfico en varios, verás que el Gp32 Converter añade al final del array a veces datos a 0 para que el array sea múltiplo de 4 bytes.

Espero q te ayude. Salu2

oankali
12/04/2005, 11:13
Yo empecé con el VC++ en Windows y luego me pasé a Linux. Ayer intenté compilar mi juego en el VC++ para usar el debugger, usé un template de los que usaba antes pero me empezó a dar errores en cosas que con el gcc iban perfectas (como hacer declaraciones del tipo "int numero = 3" dentro de un if). Moviendo esas variables como globales me compilaba, pero luego me empezó a dar errores con las imágenes incluídas como .h diciendo que sobrepasaba la cima del montículo o algo así...

Saludos

Si, hay algunas cosas que no son compatibles, pero si programas límpiamente, no suele haber problemas.
Lo de los .h no me pasa.

Mira este hilo (http://www.gp32spain.com/foros/showthread.php?p=185668#post185668) y verás que si funciona.

oankali
12/04/2005, 11:21
Te recomiendo que partas el gráfico "inmarco" en varios.

Los reseteos pueden deberse a que los GpBitBlt() que estas utilizando tienen
parámetros de coordenadas que no son múltiplos de 4, con lo cual si haces
acceso a memoria no alineado en enteros (4 bytes) -> reinicio de la consola.
También a que GpBitBlt() haga con los parámetros que le pasas accesos a memoria inválidos (no alineados en direcciones de memoria múltiplos de 4).
Por ello a veces te pasa y a veces no, dependiendo de dónde quede en memoria el gráfico en cuestión (depende de la gp32 dónde le dé por colocar
en memoria el gráfico).

Si partes el gráfico en varios, verás que el Gp32 Converter añade al final del array a veces datos a 0 para que el array sea múltiplo de 4 bytes.

Espero q te ayude. Salu2

Yo uso muchos BMPs de 320 x 240 y algunos más grandes y nunca me han dado problemas.
La única vez que me he encontrado el problema que comentas, Franxis, es usando GpBitLRBlt16(). Con GpBitBlt16() y GpTransBlt16(), tengo libertad total de posicionamiento.

Es cierto que las funciones gráficas del SDK a veces son muy puñeteras.
Pero el alineamiento suele dar problemas solo en el tamaño original de tu BMP, no en el tamaño ni la posición en el que lo quieres dibujar. Tu BMP hace 320 x 240, o sea que en principio ningún problema.

Pero como solo programo en 16bits, no puedo asegurar que pase lo mismo con las de 8 bits.

Oankali.

Puck2099
12/04/2005, 11:31
Yo uso muchos BMPs de 320 x 240 y algunos más grandes y nunca me han dado problemas.
La única vez que me he encontrado el problema que comentas, Franxis, es usando GpBitLRBlt16(). Con GpBitBlt16() y GpTransBlt16(), tengo libertad total de posicionamiento.

Es cierto que las funciones gráficas del SDK a veces son muy puñeteras.
Pero el alineamiento suele dar problemas solo en el tamaño original de tu BMP, no en el tamaño ni la posición en el que lo quieres dibujar. Tu BMP hace 320 x 240, o sea que en principio ningún problema.

Pero como solo programo en 16bits, no puedo asegurar que pase lo mismo con las de 8 bits.

Oankali.

Hablando de tamaños no múltiplos de 4, yo uso muchos BMPs convertidos a .h para las animaciones de personajes, items, etc. Por lo general su tamaño es el mínimo posible para ahorrar espacio en memoria, pero eso da por ejemplo 297x331 pixels. Según comentais esto es una fuente de problemas, ¿no?, ¿debería agrandarlo hasta el siguiente múltiplo de 4?

Por otro lado, ¿también es problemático que cargue un trozo de gráfico con los GpBitBlt no múltiplo de 4? (por ejemplo, de un archivo .h ya múltiplo de 4, pintar un trozo de 27x35 que se corresponderá a un sprite)

Gracias

oankali
12/04/2005, 11:35
Todos tus BMPs tienen que ser múltiplos de 4, problemas asegurados.
La zona que quieres dibujar no tiene que serlo, sino vaya faena :)

Puck2099
12/04/2005, 11:40
Todos tus BMPs tienen que ser múltiplos de 4, problemas asegurados.

Vaya, pues eso no lo especificaban en la documentación del SDK, ¿verdad?. Ya les vale... Esta tarde me tocará modificar todos los gráficos y el código asociado (eso me pasa por no usar las constantes de ancho y alto de cada gráfico y escribirlas directamente) :(


La zona que quieres dibujar no tiene que serlo, sino vaya faena :)

Bueno, había pensado sino en hacer transparente lo que sobrara, pero sí, así me ahorro mucho trabajo :)

Saludos

Puck2099
13/04/2005, 00:30
Bueno, he seguido vuestros consejos, he hecho todas las imágenes múltiplo de 4 y revisada una función donde se perdían algunos punteros y de momento, en todas las pruebas que llevo, no se me ha vuelto a reiniciar la consola :)

Sin embargo ahora tengo un problemilla, desde que empecé a pintar la imagen "immarco" en 4 trozos, para ahorrarme pintar el centro, se produce un parpadeo continuo en los sprites que está situados sobre la primera parte del marco que se pinta (la parte superior), pero solo en la parte derecha. Como he pintado en esta imagen afecta al último dígito del tiempo (y sin embargo a los otros dos que se pintan juntos no les afecta) y los iconos de las vidas, pero también a la parte del buzo que se "asome" por ahí encima.

¿Tenéis idea de a qué puede deberse?, ¿algo que ver quizá con la sincronización horizontal o vertical?

Saludos

oankali
13/04/2005, 08:26
Cuando hay un problema de sincronización, en principio es la parte derecha de la pantalla, de arriba a abajo, que se ve afectada, pero no un solo trocito.
Yo apuntaría a un problema con el manejo de tus dos superfícies, porque supongo que utilizarás dos ¿no? Mira si no estás dibujando sobre la superfície actualmente en pantalla en lugar del back buffer.

Puck2099
13/04/2005, 09:09
Cuando hay un problema de sincronización, en principio es la parte derecha de la pantalla, de arriba a abajo, que se ve afectada, pero no un solo trocito.
Yo apuntaría a un problema con el manejo de tus dos superfícies, porque supongo que utilizarás dos ¿no? Mira si no estás dibujando sobre la superfície actualmente en pantalla en lugar del back buffer.

Sí, tengo dos superficies.

Lo raro es que dibujo en todas las funciones sobre la misma superficie (gpDraw[nflip]), pero el fallo gráfico solo se da en ese trozo, sin afectar a partes de sprites que queden fuera. Como dije anteriormente, si me acerco con el "buzo" de forma que queda la cabeza sobre esa zona y el cuerpo por debajo, solo parpadea la cabeza, el cuerpo se ve perfectamente.

Otra cosa que he notado es que creo que cuanto más a la derecha de ese trozo, más deprisa parpadea. Sin embargo, lo que es el fondo en sí no parpadea, solo los sprites que se pinten encima.

No sé si me he explicado bien...

Muchas gracias por la ayuda :)

oankali
13/04/2005, 09:47
A ver, he intentado imaginarme como lo haría yo si quisiera conseguir ese efecto a drede. Aquí tienes dos soluciones:


1. Preparo toda la pantalla en el back buffer
2. Activo el back buffer con lo que lo veo en pantalla
3. Añado un pequeño retardo porque mi programación es la leche y el juego va demasiado acelerado ;)
4. Dibujo una parte del fondo en esa pequeña zona directamente en la pantalla.
5. Vuelvo al 1.


1. Preparo toda la pantalla en el back buffer
2. Activo el back buffer con lo que lo veo en pantalla
3. Pequeño retardo por la misma razón que antes :)
4. Copio lo que hay en pantalla en el back buffer
5. Dibujo una parte del fondo en esa pequeña zona en el back buffer
6. Activo el back buffer con lo que lo veo en pantalla
7. Vuelvo al 1.


A ver si lo que pasa es que estás haciendo eso sin querer.
Y para saber si es un problema de sincronización, intenta cambiar la velocidad de la CPU a ver que pasa.

Puck2099
13/04/2005, 09:54
Pues los pasos que hago son:
1. Preparo toda la pantalla en el back buffer.
2. Añado un pequeño retardo porque mi programación es la leche y el juego va demasiado acelerado :D
3. Activo el back buffer con lo que lo veo en pantalla.
4. Vuelvo a 1.

Por otro lado, ¿podrías explicarme qué se hace mal en el segundo caso que explicas, please? Es que no veo ningún fallo que pudiera hacer parpadeos.

Muchas gracias de nuevo :brindis:

oankali
13/04/2005, 10:32
En el paso 2 muestro la pantalla correcta durante el lapso de tiempo indicado en el paso 3.
En el paso 4 copio lo que hay en pantalla en el back buffer, con lo que ahora tengo las dos superfícies exactamente iguales.
En el paso 5 borro un trozo de pantalla dibujando una parte del fondo en el back buffer.
En el paso 6 muestro la pantalla incorrecta. Pero como no hay retardo y salto al paso 1, pues aparece un muy ligero parpadeo.

Puck2099
13/04/2005, 18:58
oankali, creo que mi problema era con la sincronización. He cambiado la inicialización de la consola a 133 Mhz que tenía por la de tu librería clock.c y ahora no parpadea nada :)

Te pongo las dos a ver si sabes para que valen los distintos parámetros que tenemos diferentes (los mios los saqué hace muuucho de un post de GP32x):

Mi función: GpClockSpeedChange(132000000,0x24001,2);
La tuya: GpClockSpeedChange(132000000, 0x3a011, 3);

El último parámetro creo que es un divisor de la frecuencia, o algo parecido, ¿no? Porque con mi función un segundo eran unos 4000 ticks y con la tuya son 1864.

Otra cosa, ¿qué licencia usan tus librerías?

Saludos

oankali
14/04/2005, 08:22
Mi función: GpClockSpeedChange(132000000,0x24001,2);
La tuya: GpClockSpeedChange(132000000, 0x3a011, 3);

El último parámetro creo que es un divisor de la frecuencia, o algo parecido, ¿no? Porque con mi función un segundo eran unos 4000 ticks y con la tuya son 1864.

Para ser sincero, no tengo ni idea. Nunca he conseguido entender la documentación a este respecto, ni encontrar en ningún foro una explicación decente.
Per pienso lo mismo que tu. Es más, a veces pienso que es posible encontrar configuraciones para cada velocidad en que los ticks por segundos sean siempre los mismos. Eso si, no sé como se comportará la pantalla.
Los valores que estan en clock.h no son míos, son de ThunderZ y de MrMirko.




Otra cosa, ¿qué licencia usan tus librerías?


La única librería que tiene licencia es mi OKF Font Engine, tiene un archivo adjunto que la detalla y está redactada por mi, salvo las líneas finales en mayúsculas que no recuerdo de donde las copié retocando un poco (es que era demasiado técnico para mi :)).
Todas las otras son completamente libres, haced lo que queráis con ellas.
Solo con que me citéis en vuestros programas, quedaría satisfecho, pero no es obligatorio.
También se agradecería un correito si las modificáis o las mejoráis.

Oankali.

Puck2099
14/04/2005, 09:12
Para ser sincero, no tengo ni idea. Nunca he conseguido entender la documentación a este respecto, ni encontrar en ningún foro una explicación decente.
Per pienso lo mismo que tu. Es más, a veces pienso que es posible encontrar configuraciones para cada velocidad en que los ticks por segundos sean siempre los mismos. Eso si, no sé como se comportará la pantalla.
Los valores que estan en clock.h no son míos, son de ThunderZ y de MrMirko.


Por cierto, no sabrás cuales de los valores de reloj de tu librería no dan problemas con las BLU+, ¿verdad?

Al menos mi Lady Killer funciona bien a 132 Mhz, pero a 102 Mhz vuelven a salir problemas con una ralla azul vertical bastante amplia (supongo que será por la sincronización o el refresco).

A ver si compilo mi juego con varias frecuencias y consigo que me lo pruebe algún usuario de BLU+ para hacer un listado más completo.


La única librería que tiene licencia es mi OKF Font Engine, tiene un archivo adjunto que la detalla y está redactada por mi, salvo las líneas finales en mayúsculas que no recuerdo de donde las copié retocando un poco (es que era demasiado técnico para mi :)).
Todas las otras son completamente libres, haced lo que queráis con ellas.
Solo con que me citéis en vuestros programas, quedaría satisfecho, pero no es obligatorio.
También se agradecería un correito si las modificáis o las mejoráis.

La que realmente me interesa de momento es la clock.h, al final no hago uso de tu motor de fuentes porque mi juego va a 8 bits y no necesito efectos ni nada parecido, pero muchas gracias por lo que me enviaste :)

No te preocupes que si hago cambios en tu clock.h te los mandaré por si te interesan :)

Saludos