Karoshi MSX Community

Desarrollo MSX => Desarrollo (Español/Spanish) => Mensaje iniciado por: assembler en 27 de Enero de 2012, 06:45:15 pm



Título: Corrupción en la VRAM
Publicado por: assembler en 27 de Enero de 2012, 06:45:15 pm
Buenas tardes.

Tengo el M-TANKS casi terminado, depurando fallitos allí y alla, pero se me está atascando lo que espero que sea una tontería y veo que la fecha límite para el MSXDEV'11 se me echa encima.

En su momento descubrí que acceder a la VRAM con las funciones de la BIOS me daba problemas porque ellas solitas activaban las interrupciones, así que decidí copiarlas en mi código y modificarlas lévemente para colocar EI donde me interesara.

Todo parecía ir bien hasta que hemos empezado a hacer pruebas intensas en máquinas reales.

Aleatoriamente (aunque no muy a menudo), aparecen TILES aleatorios en pantalla, se modifican sprites sin venir a cuento, aparecen sprites donde no deben cuando no deben, etc.

¿Alguien podría echarme una mano con las rutinas que uso por si hubiera metido la pata?

Estas son las funciones de acceso a la VRAM que utilizo:


vpoke_ROM:
        ld a,l
        di
        vpoke_rom_99_1:       
        out (0x99),a
        ld a,h
        and 0x3f
        or  0x40
        vpoke_rom_99_2:       
        out (0x99),a
        ld a,b
        ex [sp],hl
        ex [sp],hl
        vpoke_rom_98_3:       
        out (0x98),a
        ei
        ret
vpoke_int_ROM:
        ld a,l
        vpoke_int_rom_99_1:
        out (0x99),a
        ld a,h
        and 0x3f
        or  0x40
        vpoke_int_rom_99_2:
        out (0x99),a
        ld a,b
        ex [sp],hl
        ex [sp],hl
        vpoke_int_rom_98_3:
        out (0x98),a
        ret
direccionvram_ROM:
        ld a,l
        direccionvram_rom_99_1:
        out (0x99),a
        ld a,h
        and 0x3f
        or 0x40
        direccionvram_rom_99_2:
        out (0x99),a
        ret
   
       
llenavram_ROM:
        ld d,a
        di
        call direccionvram
               
        bucle_llenavram_rom:       
        ld a,d
        llenavram_rom_98_1:
        out(0x98),a
        dec bc
        ld a,b
        or c
        jr nz,bucle_llenavram_rom
         
        ei
        ret
llenavram_vert_ROM:
        ld d,a
        di
        bucle_llenavram_vert_ROM:       
        call direccionvram
               
        ld a,d
        llenavram_vert_rom_98_1:
        out[0x98],a
        push de
        ld de,32
        add hl,de
        pop de
        dec bc
        ld a,b
        or c
        jr nz,bucle_llenavram_vert_ROM
         
        ei
        ret
       
ram2vram_ROM:
        di
        ex de,hl
        call direccionvram
bucle_ram2vram_ROM:
        ld a,[de]
        ram2vram_rom_98_1:
        out [0x98],a
        inc de
        dec bc
        ld a,b
        or c
        jr nz,bucle_ram2vram_ROM 
        ei
        ret



Las etiquetas intermedias (ram2vram_rom_98_1, llenavram_vert_rom_98_1...) las utilizo para copiar el código en RAM y modificar las direcciones del puerto del VDP a las que indica la dirección 0x0007

La preparación de las rutinas la hago con:
fin_rutinas_video_ROM:
rutinas_vram:
        ld hl,inicio_rutinas_video_ROM
        ld de,inicio_rutinas_video_RAM
        ld bc,fin_rutinas_video_ROM-inicio_rutinas_video_ROM
        ldir
        ld a,[7]
        ld [inicio_rutinas_video_RAM+(vpoke_rom_98_3-vpoke_ROM)+1],a
        ld [inicio_rutinas_video_RAM+(vpoke_int_rom_98_3-vpoke_ROM)+1],a
        ld [inicio_rutinas_video_RAM+(llenavram_rom_98_1-vpoke_ROM)+1],a
        ld [inicio_rutinas_video_RAM+(llenavram_vert_rom_98_1-vpoke_ROM)+1],a
        ld [inicio_rutinas_video_RAM+(ram2vram_rom_98_1-vpoke_ROM)+1],a
        inc a
        ld [inicio_rutinas_video_RAM+(vpoke_rom_99_1-vpoke_ROM)+1],a
        ld [inicio_rutinas_video_RAM+(vpoke_rom_99_2-vpoke_ROM)+1],a
        ld [inicio_rutinas_video_RAM+(vpoke_int_rom_99_1-vpoke_ROM)+1],a
        ld [inicio_rutinas_video_RAM+(vpoke_int_rom_99_2-vpoke_ROM)+1],a
        ld [inicio_rutinas_video_RAM+(direccionvram_rom_99_1-vpoke_ROM)+1],a
        ld [inicio_rutinas_video_RAM+(direccionvram_rom_99_2-vpoke_ROM)+1],a
        ret



A quien se le ocurre ponerse tan tarde a probar el juego en máquinas reales, eh? a quien?
ains...



Muchas gracias.


Título: Re: Corrupción en la VRAM
Publicado por: j4mk3 en 27 de Enero de 2012, 07:57:44 pm
A mi me da que no te esperas lo necesario entre OUT i OUT hacia VRAM.
Mirate este post http://karoshi.auic.es/index.php?topic=668.0 en le apartado de Acceso contenido a la VRAM (o como acceder a la VRAM sin usar la BIOS y no morir en el intento)
y te dejo aquí la rutina que uso yo para volcado de ThePetsMode by NapalM ;).
Así ves un poco eso del tiempo de espera.

Código:
; ////////////////////////////////
; ///////// IPBVRM ///////////////
; ////////////////////////////////

; Interrupt pub buffer videoram
; VOLCA buffer de 768 bytes A VRAM screen2
; 29/12/04 Arnau Castellvi / Zona Neutra

; HL = Offset del buffer

; Cal RAM : res
; Toca   : B,C,D,E
; Retorna : res
; Usa fun.: res

IPBVRM:
ld DE,VRM_MAP
ld B,96     
ld A,E
out [99h],A
ld A,D
or 40h
out [99h],A
ld C,98h

IPBVRM0:
ld D,B
outi
nop
nop
outi
nop
nop
outi
nop
nop
outi
nop
nop
outi
nop
nop
outi
nop
nop
outi
nop
ld B,D
outi
jp nz,IPBVRM0
ret


Título: Re: Corrupción en la VRAM
Publicado por: assembler en 27 de Enero de 2012, 08:33:30 pm
Voy a meter unos cuantos NOP entre los OUT, a ver si así...

Lo que me tiene intrigado es que el código lo copié de la BIOS del Toshiba HX-10 que hay para el BlueMSX, por lo que debería ser correcta, al menos para el HX-10

¿?



Muchas gracias.


Título: Re: Corrupción en la VRAM
Publicado por: Dioniso en 27 de Enero de 2012, 09:04:43 pm
Estas son las funciones de acceso a la VRAM que utilizo:

¿Dónde está la rutina direccionvram? No la veo en el código que has puesto.


Título: Re: Corrupción en la VRAM
Publicado por: Dioniso en 27 de Enero de 2012, 09:12:33 pm
Y respecto a los OUTs de tu rutina: tampoco veo ningún problema por la espera entre OUTs. De hecho, tengo requeteprobado que un simple LD A,0 (9 t-states) es suficiente. Dos NOPs serían 10, uno más de la cuenta  ;)

O incluso LD A,$3E, ya que LD A,n sería $3E y al cargar A con $3E te puede salir una mejor compresión ... En hexadecimal LD A,$3E sería $3E, $3E.

Esto, claro, si no necesitas A en tus OUTs.


Título: Re: Corrupción en la VRAM
Publicado por: Mortimer en 27 de Enero de 2012, 09:21:18 pm
Yo también dudo mucho que sea un problema de agobio del vdp, hay ya retardos más que de sobra. Lo que sí veo es que vpoke_int_ROM y direccionvram_ROM no desabilitan las interrupcuones entre los  OUTS que establecen la dirección de memoria, así que si cae una INT en medio el puntero puede terminar en cualquier sitio y explicaría los fenómenos paranormales porque modificas la vram de forma aleaotoria...


Título: Re: Corrupción en la VRAM
Publicado por: assembler en 27 de Enero de 2012, 09:31:34 pm
vpoke_int la utilizo solo dentro de la interrupción y direccionvram solo la uso dentro de las funciones que hay ahí, no la uso sola





Título: Re: Corrupción en la VRAM
Publicado por: Dioniso en 27 de Enero de 2012, 09:33:13 pm
¿Puedes mostrar la rutina direccionvram? Igual hay algo ahí.


Título: Re: Corrupción en la VRAM
Publicado por: assembler en 27 de Enero de 2012, 10:19:19 pm
La función es direccionvram_ROM que se copia en RAM para cambiar las direcciones de los puertos según convenga


Título: Re: Corrupción en la VRAM
Publicado por: Mortimer en 27 de Enero de 2012, 10:54:29 pm
¿Va bien en todos los emuladores? ¿En qué máquinas reales falla? ¿MSX1 ó MSX2? ¿50 ó 60?


Título: Re: Corrupción en la VRAM
Publicado por: Dioniso en 27 de Enero de 2012, 11:44:17 pm
¿No será que cuando se dan ciertas coincidencias en el juego mandas más datos de los que deberías a la VRAM? ... Uff, pueden ser tantas cosas ...


Título: Re: Corrupción en la VRAM
Publicado por: pitpan en 28 de Enero de 2012, 01:13:49 am
Si sucede "de vez en cuando", lo más probable es que en algún punto del programa, mientras estás escribiendo a VRAM, se dé una interrupción que afecte a los punteros del VDP. Así, al seguir escribiendo tras ejecutar la interrupción, se haría en puntos incorrectos de la VRAM.

La otra opción - habría que ver capturas del problema - es que escribas a VRAM fuera del v-blank y sin los suficientes retardos.

Pero claro, todo esto te lo digo sin revisar tu código, que no está el horno para bollos. Recuerda que por más DI que pongas, muchas rutinas de la BIOS reactivan las interrupciones (hacen un EI que deja tus DI sin efecto).

Ánimo para depurar. A mi me pasó algo semejante, pero era porque dejaba el bit de la VDP que indicaba que sólo se disponía de 4 KB de VRAM. Todo lo que estaba por encima, dejaba de refrescarse (es RAM dinámica) y al poco se corrompían los gráficos. Por lo que cuentas, no es éste el caso.


Título: Re: Corrupción en la VRAM
Publicado por: assembler en 28 de Enero de 2012, 07:19:27 am
Últimamente solo lo he probado con el BlueMSX. Hubo una temporada que tuve linux y lo estuve probando con openMSX.

Con BlueMSX no recuerdo haber visto nada raro, aunque me consta que emulando un TurboR sí ha dado algún que otro fallo. En OpenMSX no lo he probado como para ver fallos.

En máquinas reales lo he probado en un Toshiba HX-10, un NMS8245 y un Wavy 70FD, en todos alguna vez , me ha hecho algo raro.

Tengo una rutina que dependiendo de si estamos en 50 ó 60 hz inicializa una variable, para ejecutar la interrupción siempre 50 veces por segundo: cada 5 interrupciones, me salto una, así siempre va el juego a la misma velocidad, y no se nota nada raro ni en el movimiento ni en la música. Lo leí aquí o en el MRC y la verdad es que va muy bien.



¿?


Título: Re: Corrupción en la VRAM
Publicado por: Mortimer en 28 de Enero de 2012, 09:55:03 am
Si te hace el raro en un MSX2 yo ya descartaría que se problema de velocidad, porque ni queriendo con un Z80 podrías enviar datos más rápido de los que puede procesar.

¿Y si fuera otra interrupción que no sea la del VDP la que te estuviera fastidiando? ¿Cómo cargas las roms en las máquinas? ¿Con un cartucho flash o con algo que puede generar interrupciones?


Título: Re: Corrupción en la VRAM
Publicado por: assembler en 28 de Enero de 2012, 10:13:32 am
Ahora que estoy en formato megarom, solo puedo probarlo con la MegaFlashROM SCC. Cuando iba por 32 KB podía probarlo con EXECROM




Título: Re: Corrupción en la VRAM
Publicado por: nanochess en 28 de Enero de 2012, 05:44:29 pm
Una idea por pasos para depurar (me sirvió muchísimo cuando tuve que poner código directo de VDP):
1. Aisla todo el código de VDP en un solo punto.
2. Asegurate de que los DI/EI solo se usan en ese punto y tal vez al inicio del programa.
3. Si escribes o lees del VDP (DB 98 / D3 98), debes esperar 28 ciclos antes de cambiar la dirección (D3 99). Debes visualizar el código como una lista lineal de instrucciones.
4. Las escrituras (D3 99) afortunadamente no necesitan NOPS. Se sugieren 28 ciclos antes de poner a continuación el (DB 98 / D3 98)
5. Haz una lista de todas las llamadas, pudiera ser que una rutina llama a otra que era diferente antes.
6. Si sigue fallando, desactiva partes sospechosas del código.
Como referencia, los NOP ocupan 5 ciclos.
¡Ánimo!


Título: Re: Corrupción en la VRAM
Publicado por: assembler en 31 de Enero de 2012, 02:00:11 pm
Muchas gracias a todos por vuestras respuestas. Me han servido para localizar el problema.

Había de todo un poco: no respetar tiempos, no usar el in a,(0x99), USAR CODIGO DENTRO DE LA INTERRUPCION QUE ACTIVABA LAS INTERRUPCIONES DE NUEVO...



Creo que está listo para presentarlo, a falta de darle un repasito final de betatesting y PA'RRIBA


Tengo que confesar que estuve a punto de abandonar. Puse incluso un mensaje desesperado en este foro comentando la posibilidad y pidiendo un poco más de ayuda, pero  ??? no se publicó  ??? (Al menos no se donde está)

Al volver a entrar más tarde para ver si alguien había respondido, vi que no se había publicado, lo interpreté como una señal del ciberespacio y me puse a darle más vueltas al asunto, hasta que atiné.


Título: Re: Corrupción en la VRAM
Publicado por: Mortimer en 31 de Enero de 2012, 02:05:30 pm
¡Que buena noticia  :D!


Título: Re: Corrupción en la VRAM
Publicado por: Dioniso en 31 de Enero de 2012, 02:53:36 pm
Al volver a entrar más tarde para ver si alguien había respondido, vi que no se había publicado, lo interpreté como una señal del ciberespacio y me puse a darle más vueltas al asunto, hasta que atiné.

Alabado sea el ciberespacio  :magicalstones:

Enhorabuena por el juego.


Título: Re: Corrupción en la VRAM
Publicado por: Mortimer en 01 de Febrero de 2012, 09:12:42 pm
Si hubiera visto tu post desesperado te hubiera pedido una volcado de la memoria para haberlo metido en mi emulador, porque no hubiera sido difícil añadirle algo de código 'ad hoc' para monitorizar que todas las escrituras al VDP fueran coherentes, no sólo la velocidad, si no que por ejemplo no se envíe un byte bajo de dirección de vram que luego no tenga efecto por una interrupción o un IN, o quizás listados de las posiciones que van tomando los punteros para poder revisar después, porque los fallos así intermitentes y aleatorios son puñeteros de pillar con un debugger normal

No sé si hay algo ya parecido en algún emulador, porque quizás sea una buena idea añadírselo al meisei como lo de escrituras rápidas.

(Ah, y muchas gracias por incluirme en los créditos  :D)



Título: Re: Corrupción en la VRAM
Publicado por: assembler en 02 de Febrero de 2012, 08:25:33 pm
Gracias a tí por la ayuda prestada, y por la que me podías haber prestado.  ;)


¿Eso que comentas del código 'ad hoc' me lo puedes explicar?


Título: Re: Corrupción en la VRAM
Publicado por: Mortimer en 02 de Febrero de 2012, 10:42:36 pm
Me refería a modificar el emulador con código específico para acorralar el problema. Se puede hacer casi cualquier cosa desde dentro para intentar forzar el fallo, poner alertas todo lo complejas que quieras, trazar escrituras o lecturas, medir timings del vdp, acortar o alargar los ciclos por INT, contar ciclos...