Estreno nuevo subforo y avances emulador Spectrum dcrespo

Avatar de Usuario
Eremus
Mensajes: 44
Registrado: 01 May 2022 18:10
Agradecido : 70 veces
Agradecimiento recibido: 75 veces

Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor Eremus » 05 Jun 2022 11:10

Hola!

Mensajito para estrenar el nuevo subforo -thumbup

Por cierto, al nombre del subforo le falta una erre, que así como está parece escrito por el primo Balki (toma referencia retro -grin ).

En relación al emu de Spectrum dejo un par de imágenes de los últimos avances:

DREAMWALKER2.jpg
DREAMWALKER2.jpg (61.74 KiB) Visto 997 veces


DREAMWALKER1.jpg
DREAMWALKER1.jpg (54.49 KiB) Visto 997 veces


Saludos ;)

jltursan
Mensajes: 4522
Registrado: 20 Sep 2011 13:59
Ubicación: Madrid
Agradecido : 629 veces
Agradecimiento recibido: 1468 veces
Contactar:

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor jltursan » 05 Jun 2022 12:18

Ya decía yo que me sonaba...eso emplea Nirvana y por tanto requiere una temporización super precisa, ¿no? -shock

ackerman
Mensajes: 315
Registrado: 05 Feb 2019 21:32
Ubicación: Asturias
Agradecido : 131 veces
Agradecimiento recibido: 257 veces

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor ackerman » 05 Jun 2022 12:24

Eremus escribió:Hola!
Por cierto, al nombre del subforo le falta una erre, que así como está parece escrito por el primo Balki (toma referencia retro -grin ).

-grin -grin Si, fue que se lo pasé mal escrito a @ron. Probe hombre, tiene merecido un altar, que le he dado la chapa para que creara el subforo.

Tiene muy buena pinta el modo multicolor. -thumbup

Las imágenes adjuntas en los mensajes, si quieres que se vean como preview, si las bajas de resolución, se ven en el propio mensaje. Puedes comprobarlo con el botón de vista previa. No te se decir de memoria, que resolución mínima necesita para verse, pero creo que con 640x480, ya se ven. Si pones archivos de resolución muy grandes, requiere pinchar en ellos.

Avatar de Usuario
Eremus
Mensajes: 44
Registrado: 01 May 2022 18:10
Agradecido : 70 veces
Agradecimiento recibido: 75 veces

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor Eremus » 05 Jun 2022 13:08

jltursan escribió:Ya decía yo que me sonaba...eso emplea Nirvana y por tanto requiere una temporización super precisa, ¿no? -shock

Si, usa el motor Nirvana. Por lo que sé, requiere por una parte que la Contended Memory este emulada y, por otra, que el render de pantalla sea razonablemente eficiente y sincronizado.

La Contended memory ya estaba implementada en el emu de David y el render de pantalla se hacia en otro hilo. Con los últimos ajustes, David consiguio una sincronización muy buena pero no suficiente.

Lo que he conseguido (un poco a "martillazos" y pendiente de repasar/optimizar) es mejorar lo suficiente la sincronización pasando el render a monohilo y además, usando un truquillo para que todo cuadre (dibujo la parte izquierda y la parte derecha de la main screen desincronizadas medio scanline). No lo he testado de manera extensiva pero, al menos hasta la tercera pantalla, parece que Dreamwalker se ve correcto.

Otras cosas menos exigentes como Aquaplane, ahora se ven creo que perfectas. El borde esta perfectamente alineado pero me queda la duda de las montañas del fondo que en unos emus muestran el color parpadeante y en otros un color fijo. No tengo un Spectrum real a mano para probarlo.

Aun queda optimizar las cosas un poco. En algunas situaciones, loop de CPU más render superan los 20 milisegundos cosa que no es suficiente. También he probado la demo del motor Nirvana de Einar Saukas y aun aparecen algunos glitches. Necesita mas trabajo pero creo que la cosa llegará a buen termino.

ackerman escribió:Las imágenes adjuntas en los mensajes, si quieres que se vean como preview, si las bajas de resolución, se ven en el propio mensaje.

¡Hecho! Muchas gracias por el tip ;)

Avatar de Usuario
dcrespo3d
Mensajes: 137
Registrado: 04 Nov 2020 08:51
Agradecido : 121 veces
Agradecimiento recibido: 154 veces

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor dcrespo3d » 05 Jun 2022 19:47

Hola, muchas gracias Víctor por currarte estos últimos cambios. Prometo mirarlos cuando pueda. Llevo todo el día montando el vídeo de RetroReal y ahora tengo que salir un poco a la calle a que me de el aire, pero tiene muy buena pinta. El rótulo de DreamWalker a mí no se me veía perfecto y tú parece que lo clavas.
DavidPrograma en YouTube, GitHub

Avatar de Usuario
dcrespo3d
Mensajes: 137
Registrado: 04 Nov 2020 08:51
Agradecido : 121 veces
Agradecimiento recibido: 154 veces

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor dcrespo3d » 06 Jun 2022 21:44

Hola Victor,

He podido probar tu código, al principio cascaba una y otra vez, menos mal que recordé que mencionaste que lo estabas desarrollando para 16:9, lo puse así y ya lo he podido probar. El multicolor va perfecto y no parpadea nada. -thumbup -thumbup

Algunas cosas que estaban cuidadosamente ajustadas dejan de funcionar. Me refiero específicamente a la temporización de los juegos y el sonido del beeper, que ha quedado destrozado. Manic Miner ahora va mucho más rápido, y la música de Arkanoid suena muy sucia.

Lo malo del sonido del sonido hecho con PWM es que es sensible a variaciones temporales más pequeñas que el periodo correspondiente a la frecuencia más alta audible por el oído humano (20000Hz -> 50 microsegundos). Utilizando bien el PWM se puede crear música polifónica, pero la temporización incorrecta guarrea el sonido.

Pienso que lo que quizás habría que hacer es, instrucción a instrucción, calcular la coordenada (X,Y) del framebuffer correspondiente al tstate actual, y actualizar los pixels del framebuffer unos pocos pixels a unos pocos pixels, al menos en la zona de borde para que los efectos de borde se conserven. Quizás sea demasiado lento para la zona del bitmap, pero sería la forma de hacer una temporización exacta de los gráficos.

El spectrum 48K tiene 69888 tstates por frame, lo que corresponde a un framebuffer "virtual" de 448x312, teniendo en cuenta que la ULA pinta 2 pixels por tstate.

Las 312 scanlines se distribuyen en 64 de borde superior, 192 de bitmap, y 56 de borde inferior (64+192+56).

Las scanlines de bitmap abarcan 224 tstates, de los cuales 128 corresponden al bitmap y los 96 restantes al borde, podemos considerarlo como 48+128+48 tstates, o en pixels 96+256+96 = 448.

El caso es que el framebuffer real es de 320x240 o 360x200 según estemos en 4:3 o 16:9, y estoy planteando un framebuffer virtual de 448x312 (139776 bytes).

No se si ese framebuffer virtual podría estar en PSRam (en SRAM no nos cabe). Podríamos tener 2 scanlines en SRAM (896 bytes) o en alguna memoria aún más rápida (@ackerman sabe más del tema), e ir volcando scanline a scanline al buffer virtual. Después, en el thread de vídeo, hacer un blit del buffer virtual al framebuffer real. Puede que sea más lento que el caballo del malo... o puede que no.

Con ese esquema, seguramente funcionaría el banner de letronas del Sentinel (scroll de letras en el borde superior).

Espero que lo que he dicho del sonido no lo veas como una crítica negativa, en realidad agradezco mucho tus aportes. La mayoría de la gente sólo pide funcionalidades sin aportar nada, pero tú te has puesto a picar código y eso se valora muchísimo -thumbup
DavidPrograma en YouTube, GitHub

Avatar de Usuario
Eremus
Mensajes: 44
Registrado: 01 May 2022 18:10
Agradecido : 70 veces
Agradecimiento recibido: 75 veces

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor Eremus » 07 Jun 2022 00:25

dcrespo3d escribió:He podido probar tu código, al principio cascaba una y otra vez, menos mal que recordé que mencionaste que lo estabas desarrollando para 16:9, lo puse así y ya lo he podido probar. El multicolor va perfecto y no parpadea nada. -thumbup -thumbup

Algunas cosas que estaban cuidadosamente ajustadas dejan de funcionar. Me refiero específicamente a la temporización de los juegos y el sonido del beeper, que ha quedado destrozado. Manic Miner ahora va mucho más rápido, y la música de Arkanoid suena muy sucia.

Si, la temporización habrá que revisarla posteriormente si conseguimos video bien sincronizado y suficientemente rápido. En el branch monohilo me estoy centrando en intentar conseguir el mejor video posible y, como ya has visto, ahora no me estoy preocupando de ser muy aseado. Solo hacer pruebas y profiling para compartirlo, recibir feedback, que vayamos viendo cual es el mejor enfoque y que cosas pueden funcionar y no.

Pienso que lo que quizás habría que hacer es, instrucción a instrucción, calcular la coordenada (X,Y) del framebuffer ...
...
...
No se si ese framebuffer virtual podría estar en PSRam (en SRAM no nos cabe). Podríamos tener 2 scanlines en SRAM (896 bytes) o en alguna memoria aún más rápida (@ackerman sabe más del tema), e ir volcando scanline a scanline al buffer virtual. Después, en el thread de vídeo, hacer un blit del buffer virtual al framebuffer real. Puede que sea más lento que el caballo del malo... o puede que no.

Este es, precisamente, el feedback al que me referia :)

Precisamente esta tarde, he empezado a codificar una prueba para renderizar tstate por tstate a ver como queda la cosa. Todavia estoy en ello aunque me temo que, al menos las primeras versiones, seran lentas. Ahí es donde habrá que atracar al señor Ackerman -507 que parece ser un monstruo en optimización. Lo que comentas de usar un framebuffer virtual quizá pueda acelerar. Si es así, como bien dices, se podría usar otro thread para volcarlo a framebuffer real.

Con ese esquema, seguramente funcionaría el banner de letronas del Sentinel (scroll de letras en el borde superior).

Eso ya seria la leche -grin

Espero que lo que he dicho del sonido no lo veas como una crítica negativa, en realidad agradezco mucho tus aportes. La mayoría de la gente sólo pide funcionalidades sin aportar nada, pero tú te has puesto a picar código y eso se valora muchísimo -thumbup

En absoluto. Soy además consciente de mis limitaciones. Hasta hace unas semanas, no sabia ni la decima parte de lo que sé ahora sobre emulación y agradezco muchísimo lo amables y pacientes que estáis siendo.

Un saludo ;)

ackerman
Mensajes: 315
Registrado: 05 Feb 2019 21:32
Ubicación: Asturias
Agradecido : 131 veces
Agradecimiento recibido: 257 veces

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor ackerman » 07 Jun 2022 18:43

Enhorabuena a todos. Esto es lo que presta, que se puede compartir todo, y pueden salir cosas muy interesantes. -drinks -drinks
Yo hice pruebas con multicolor, una era cuando se escribía directamente en posiciones de memoria de video, al vuelo y otra en donde la decodificación de instrucciones de cpu por deteccion de tstates por scanline, juraría. También hice detección de cambio de tiles, y dibujar sólo los que cambiaban. Todo esto fue cuando aun era lento el core de @zx81 (Jose Luis Sanchéz), así que lo dejé pochar ahi, junto con más cosas, y cuando ya tiró a toda velocidad, no las retomé. El multicolor en x86 lo hacia bien, pero claro, en x86, como si se pone uno a dibujar pixel a pixel definiendo un pixel como si fuera un polígono, y a dibujar en plan OpenGL, va todo sobrao, da igual, que se haga todo lento, que los PC's van sobraos.

La idea de un buffer auxiliar de @dcrespo3d, es factible. Puede que valga con sólo un par de scanlines, y no haga falta todo. Mientras que la parte del buffer auxiliar se le de todo masticado, simplificando a simples asignaciones o memcpy de 32 bits, en la parte del bucle de decodificación de CPU, es factible. Tiene que ser máxima velocidad, copiar un scanline a saco.
Lo más rápido que existe es crear un buffer DMA en SRAM con heap_caps_malloc y MALLOC_CAP_DMA Tiene que ser de este tipo, para garantizar 32 bits y controlado por el módulo de DMA. Esto es lo más rápido, el problema, es si el sistema está muy saturado, que entonces, el DMA pierde la eficiencia. También esta el copiado asíncrono esp_async_memcpy, pero lo mismo, si está muy saturado, pierde la eficiencia. Recordemos, que las librerias de bitluni y fabgl también estan usando el DMA, así que si no orquestamos todo, puede ser un desastre.
Hay que ir podando cosillas, sobre todo en las que más se ejecuten por unidad de tiempo. El ESP32 no es que el coprocesador sea malo, sino que la gestión hasta ahora del mismo, es muy penosa. Así que salvo que se hagan operaciones flotantes en modo ristra de tropecientos números a saco, mejor evitarlos. Quitar también divisiones, restos y multiplicaciones tanto de enteros, como de flotantes.

Código: Seleccionar todo

inline uint8_t CPU::delayContention(uint32_t currentTstates)
{
 ...
 int modulo = halfpix % 8;
}

Cambiarlo por:

 return wait_states[(halfpix & 7)];
 


Y lo más importante, el ESP32 es como el paso del 486 al Pentium, la caché lo es todo. Los 4 KB de caché, no hacen que vaya al doble o triple de velocidad, sino de 100 a 1000 veces más rápido. Así que hay que hacer que caiga la mayor parte de cosas en la caché. Para ello, hay que usar datos pequeños, direccionamiento e indireccionamiento a memoria, lo que viene siendo arrays o punteros, y evitar la pila (el GOTO es la auténtica salud -grin -grin ).
Los task de multihilo penalizan la caché, dado que hay conmutación de tarea.

Código: Seleccionar todo

inline uint8_t Mem::readbyte(uint16_t addr) {
    uint8_t page = addr >> 14;
    switch (page) {
    case 0:
        return rom[romInUse][addr];
    case 1:
        return ram5[addr - 0x4000];
    case 2:
        return ram2[addr - 0x8000];
    case 3:
        return ram[bankLatch][addr - 0xC000];
    }
}

El inline aunque en x86 vale para muchas cosas, en ESP32, suele valer para algo mucho más pequeño que el switch, por ejemplo, para una asignación de una variable o dos, el resto no lo suele meter en inline. Esta parte es más rápido meterlo sin switch:

Código: Seleccionar todo

extern "C" inline uint8_t fast_readbyte(uint16_t addr)
{
  unsigned char idRomRam = (addr>>14); 
  if (idRomRam == 0)
  {
   return (gb_local_cache_rom[rom_in_use][addr]);
  }
  else
  { 
   return (gb_local_cache_ram[(gb_ptr_IdRomRam[idRomRam])][(addr & 0x3fff)]); 
  }


Y de está forma, se puede hacer otro podado. Como es una placa TTGO VGA32 v1.4, donde hay más RAM, se puede aplicar el truco de @zx81 (Jose Luis Sanchéz), de evitar el chequeo (if (idRomRam == 0) ) del banco 0, que es usar 16KB de RAM, de forma, que al hacer una lectura, lees del puntero a ROM, y al escribir, escribes a un puntero RAM de 16 KB. De esta forma, nunca se escribe a ROM, y la lectura y escritura es inmediata, a costa de sacrificar 16 KB de RAM. Se hace siempre acceso a array de memoria sin tener que usar el if. Este podado, ya permite meterlo en un #define o inline puro auténtico.

Al ESP32, le encanta el operador ternario ( ?: ).

El RTOS no es un SO, pero si es un planificador de tareas avanzado, digamos que actua como un embudo. La forma que tiene de predecir, es con conteo de lo que ha pasado hasta ahora. Así que si se optimiza demasiado, y la cadencia no es constante, lo que haremos es saturarlo, igual que si tiramos demasiado agua de golpe y paramos en seco. Si se lo damos como tiene que ser, al final, va todo en armonia. Es decir, que en algunos casos hay que hacer justo lo contrario, ralentizar, para garantizar la cadencia constante.

Hay muchos más trucos, pero con esto ya se puede ver por donde tirar.

Esta semana, si saco tiempo, desempolvaré lo que tenía hecho del multicolor, y miro más cosas que puedan venir bien.

Avatar de Usuario
Eremus
Mensajes: 44
Registrado: 01 May 2022 18:10
Agradecido : 70 veces
Agradecimiento recibido: 75 veces

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor Eremus » 07 Jun 2022 19:59

¡Jelou again!

Ya he implementado y probado una primera versión lo mas sincronizada posible al Tstate:

- He probado las demos de los motores Bifrost*2, Nirvana y Nirvana+. He probado también juegos que usan el motor Nirvana (Dreamwalker, Stormfinch, El Stompo, Sunbucket, Yazzie, Zoomblox) y se ven perfectos al 100% aunque, para ello, he tenido que hacer un ajuste en la función delayContention (retrasar 53 tstates la aplicación de los delays) que no se muy bien porque es necesario. Quizá compensa las imprecisión que pueda haber respecto a una CPU y ULA real:

Código: Seleccionar todo

inline uint8_t CPU::delayContention(uint32_t currentTstates)
{
    static uint8_t wait_states[8] = { 6, 5, 4, 3, 2, 1, 0, 0 }; // sequence of wait states

   currentTstates += 1;    // delay states one t-state BEFORE the first pixel to be drawn
   int line = currentTstates / 224;    // each line spans 224 t-states

   // only the 192 lines between 64 and 255 have graphic data, the rest is border
   if (line < 64 || line >= 256) return 0;
   
   // only the first 128 t-states of each line correspond to a graphic data transfer
   // the remaining 96 t-states correspond to border
   int halfpix = currentTstates % 224;

   //if (halfpix >= 128) return 0; <- ESTA ERA LA LINEA ORIGINAL QUE PIENSO QUE NO ES CORRECTA. AUNQUE BIFROST*2 FUNCIONA.

   //if (halfpix < 72 || halfpix >= 200) return 0; <- CON ESTO, QUE CREO MAS CORRECTO, BIFROST*2 TAMBIEN FUNCIONA OK.

   if (halfpix < 72 - 53 || halfpix >= 200 - 53) return 0; // ASI BIFROST*2 NO SE VE PERFECTO. NIRVANA SI.

   int modulo = halfpix % 8;
   return wait_states[modulo];
}


- La demo de Nirvana+ (con el mismo retardo que Nirvana) se ve perfecta al 99%. Hay un glitch casi imperceptible en un par de posiciones. Supongo que problemas de precisión también.

- El loop de CPU+Render de pantalla supera los 20 ms. aunque esperaba que fuera mucho mas lento. En mis pruebas la cosa esta entre 20-26 ms. dependiendo del escenario. Espero que se pueda subsanar posteriormente con optimizaciones varias.

- Me ha llamado la atención que he llegado a ver diferencias, antes y después de cada DO_Z80_INSTRUCTION, de hasta 31 Tstates. Supongo que eso resta precisión a la emulación. Quizá, en esos casos, habría que intercalar dibujado de pixeles "intrainstrucción".

- Si no veis el dibujado del borde es normal. Por ahora no estoy dibujándolo.

Si queréis trastear / colaborar / opinar / curiosear / *ar: -grin

https://github.com/EremusOne/ZX-ESPectr ... e/monohilo

Recordad que hay que probarlo en modo 16:9 por ahora y que es algo MUY preliminar. No os asustéis mucho del código ;)

Avatar de Usuario
zx81
Mensajes: 469
Registrado: 23 Feb 2013 21:31
Agradecido : 87 veces
Agradecimiento recibido: 223 veces

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor zx81 » 07 Jun 2022 20:24

No es preciso usar precisión de t-state para Nirvana, ni para nada que haya encontrado yo, en realidad. La ínclita demo Paralaktica (solo 128k), obliga a no tener un desfase de más de 4 t-states. La ULA pinta 8 pixels en bloque cada 4 t-states y no hay manera de cambiar nada en medio.

Por cierto, en esa rutina, si la división es mala, el cálculo del módulo es el puñetero demonio en casi todas las plataformas y esa función se llama muy a menudo.

El dibujado de la pantalla cambió radicalmente entre JSpeccy y ZXBaremulator, para no tener que hacer cálculos, aunque a la PI le sobra tiempo para aburrirse. La idea es llevar un puntero con unos contadores de pantalla que se mueve por columnas en lugar de por pixeles. En una línea de 224 t-tstates tienes 56 columnas y no hace falta más precisión. Te mueves conforme pintas, y con los punteros bien situados, pintas el borde y la pantalla al vuelo.

Solo es una idea... :roll:
Cuando utilizo una palabra, esa palabra significa, exactamente, lo que yo quiero que signifique. Ni más, ni menos.
Humpty Dumpty

Empieza a jugar sin tener que compilar: Emulador JSpeccy
ZX Spectrum bare-metal para Raspberry PI ZXBaremulator

Avatar de Usuario
Eremus
Mensajes: 44
Registrado: 01 May 2022 18:10
Agradecido : 70 veces
Agradecimiento recibido: 75 veces

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor Eremus » 08 Jun 2022 03:44

-woot_jump -groupwave

IMG_20220608_033645.jpg
IMG_20220608_033645.jpg (113.13 KiB) Visto 666 veces


IMG_20220608_033147.jpg
IMG_20220608_033147.jpg (140.31 KiB) Visto 666 veces


IMG_20220608_033111.jpg
IMG_20220608_033111.jpg (123.37 KiB) Visto 666 veces


Me voy a la cama que ya está bien ya -grin

Mañana explico los detalles :)

Avatar de Usuario
dcrespo3d
Mensajes: 137
Registrado: 04 Nov 2020 08:51
Agradecido : 121 veces
Agradecimiento recibido: 154 veces

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor dcrespo3d » 08 Jun 2022 17:59

Gracias @zx81 por el detalle clave de que la resolución mínima en el borde son 4 tstates = 8 pixels. Así se van a poder hacer escrituras de 32 bits que son mucho más rápidas que byte a byte.

Otro detalle es que el tstate 0 no corresponde con la esquina superior izquierda del "framebuffer virtual" de 448x312, sino 96 pixels a la derecha, es decir, a la altura del borde izquierdo:

spectrum-screen-tstates.png
spectrum-screen-tstates.png (2.22 KiB) Visto 611 veces


El tstate 14336, a partir del cual (bueno, el anterior) empieza a haber contención de memoria, se corresponde con la esquina superior izquierda del bitmap.

Es interesante considerar las columnas de 8 pixels / 4 tstates, quizás para dibujar cada columna en bloque.

Si no usáramos framebuffer virtual y dibujáramos en framebuffer real, habría que considerar cómo quedan las columnas con respecto al framebuffer real de 320x240...

spectrum-screen-tstates-320x240.png
spectrum-screen-tstates-320x240.png (1.78 KiB) Visto 611 veces


o 360x200:

spectrum-screen-tstates-360x200.png
spectrum-screen-tstates-360x200.png (1.75 KiB) Visto 611 veces


A 360x200 nos queda una columna a medias... pero por lo menos queda todo alineado a 4 bytes para que las escrituras sean rápidas.

Y no, no me olvido de los pulsos de sincronismo horizontal y vertical, sólo no los tengo en cuenta para hacer el dibujo de dónde quedaría la imagen relacionada con los tstates -grin
DavidPrograma en YouTube, GitHub

Avatar de Usuario
Eremus
Mensajes: 44
Registrado: 01 May 2022 18:10
Agradecido : 70 veces
Agradecimiento recibido: 75 veces

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor Eremus » 09 Jun 2022 15:12

Hola! Ahora que tengo un ratillo os cuento como va la cosa:

Como se podía ver en las fotos que puse en mi anterior post, todos los motores gráficos que he probado (Bifrost*2, Nirvana y Nirvana+) ya funcionan a la perfección. Como era de suponer faltaba precisión así que me puse manos a la obra y ahora se emula el proceso de dibujado de la ULA con precisión siguiendo las directrices que indico @zx81 en su ultimo post (Gracias! -thumbup ).

Al hacerlo así, ha quedado confirmada la información que puso @dcrespo3d:

dcrespo3d escribió:Otro detalle es que el tstate 0 no corresponde con la esquina superior izquierda del "framebuffer virtual" de 448x312, sino 96 pixels a la derecha, es decir, a la altura del borde izquierdo

Ahora la función delayContention no necesita ajustes de ningún tipo: estaba correctamente ajustada.

La primera consecuencia de todo esto es la velocidad. Llamar a la función ALU_video (que es la que va volcando información gráfica al backbuffer VGA) para cada incremento de tstates genera una sobrecarga importante. Cierto es que tras ajustarla para que solo vuelque información cada 4 tstates la cosa ha mejorado pero estando bastante bien (entre 20-22 ms. loop de CPU + Video en juegos que "machacan" el video), no es suficiente.

Además de procurar optimizar el código lo mejor que he sabido, he implementado dos técnicas para acelerar las cosas que aun tengo que testear mas ya que hay escenarios donde generan beneficio y otros donde no tanto:

- Marcar en un array, desde la función poke8, que es la que escribe a memoria, las posiciones de memoria de video que están "sucias" para solo pintarlas si es así. Esto mejora en algunos escenarios pero en otros no tanto. Necesita mas análisis y/o optimización.

- Evitar llamar a la función ALU_video desde funciones de Z80ops que incrementan tstates si la suma de ese incremento no hace que queden mas de 4 tstates pendientes de dibujar. Esto, al igual que la técnica del array de posiciones sucias, no tengo muy claro si ayuda o no.

Cuando este todo bien operativo (falta el tema del borde que, lamentablemente, algo de tiempo consumirá) empezare a estudiar las sugerencias de @Ackerman que, por ahora, escapan un poquillo a mi nivel y tendré que estudiar un poco antes.

La ultima versión, que tiene el código bastante mas aseado, la tenéis, como siempre, en:

https://github.com/EremusOne/ZX-ESPectr ... e/monohilo

Recordad eso si:

- Por ahora solo Spectrum 48K, en otras roms no funcionará bien.
- Por ahora solo 16/9.
- No hay bordes aun (pronto los restauro).
- La temporización se puede activar con CPU_PER_INSTRUCTION_TIMING en hardconfig.h, pero ahora no parece ser adecuada. Probablemente habrá que hacer ajustes.

Avatar de Usuario
Kyp
Mensajes: 746
Registrado: 03 Oct 2013 17:13
Agradecido : 87 veces
Agradecimiento recibido: 245 veces

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor Kyp » 10 Jun 2022 22:05

A nivel de HW, para la ULA, que también tiene un contador horizontal y uno vertical, el 0-0 es el primer pixel de la zona de bitmap.
En horizontal de 0 a 255 son los pixeles, 256 a 319 borde derecho, 320 a 415 blanking (no hay imagen), y 416 a 447 borde izquierdo.
En vertical de 0 a 191 pixeles, 192 a 247 borde inferior, 248 a 255 blanking (no hay imagen), y 256 a 311 borde superior.

Para ser más exactos, esas coordenadas se corresponden a cuando se lee la memoria, pero desde que se lee hasta que se dibujan los pixels en pantalla pasa un tiempo. Si dividimos una línea horizontal en slots de 16 pixeles, la memoria se lee en los instantes 9 y 13 bitmap, y 11 y 15 atributos. Pero hasta el instante 4 del slot siguiente no empieza a pintar los primeros 8 pixeles y en el instante 12 los siguientes, es decir, que la imagen va con 12 pixeles de retraso. Todo este lio es para juntar los accesos a la memoria que hace la ULA lo más posible para que le quede tiempo a la CPU para poder leer también al menos una vez en cada slot sin tener que meter más lógica para arbitrar los accesos.

Los pulsos de sincronismo no tienen ese retraso que si tiene la generación de la imagen.

Avatar de Usuario
Eremus
Mensajes: 44
Registrado: 01 May 2022 18:10
Agradecido : 70 veces
Agradecimiento recibido: 75 veces

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor Eremus » 11 Jun 2022 00:48

Kyp escribió:A nivel de HW, para la ULA, que también tiene un contador horizontal y uno vertical, el 0-0 es el primer pixel de la zona de bitmap.
En horizontal de 0 a 255 son los pixeles, 256 a 319 borde derecho, 320 a 415 blanking (no hay imagen), y 416 a 447 borde izquierdo.
En vertical de 0 a 191 pixeles, 192 a 247 borde inferior, 248 a 255 blanking (no hay imagen), y 256 a 311 borde superior.

Para ser más exactos, esas coordenadas se corresponden a cuando se lee la memoria, pero desde que se lee hasta que se dibujan los pixels en pantalla pasa un tiempo. Si dividimos una línea horizontal en slots de 16 pixeles, la memoria se lee en los instantes 9 y 13 bitmap, y 11 y 15 atributos. Pero hasta el instante 4 del slot siguiente no empieza a pintar los primeros 8 pixeles y en el instante 12 los siguientes, es decir, que la imagen va con 12 pixeles de retraso. Todo este lio es para juntar los accesos a la memoria que hace la ULA lo más posible para que le quede tiempo a la CPU para poder leer también al menos una vez en cada slot sin tener que meter más lógica para arbitrar los accesos.

Los pulsos de sincronismo no tienen ese retraso que si tiene la generación de la imagen.

La emulación de ULA que he implementado por ahora solo dibuja el bitmap y parece que se sincroniza bien. Ahora que ya estoy implementando el dibujado del borde de la forma mas fiel precisa, esta información me viene de perlas. Muchas gracias!

La cosa va mejorando por momentos y soy bastante optimista viendo como, poco a poco, van mejorando los tiempos. En las primeras versiones de la emulación de ULA sacaba estos tiempos medios (en microsegundos), medidos en la pantalla inicial de Dreamwalker que usa Nirvana:

CPU + VIDEO 20112 / CPU 13102 / VIDEO 7010

Las ultimas mediciones tras optimizar aquí y allá ya empiezan a pintar bien :)

CPU + VIDEO 18166 / CPU 11801 / VIDEO 6365

Cuando implemente el dibujado del borde, los tiempos subirán un poquillo pero creo que no será demasiado ni nada que no se pueda compensar posteriormente con algunas (o todas -grin) de las mejoras al core de @zx81 que @ackerman ha implementado en su fork.

En otro orden de cosas, no hago mas que indagar en el megahilo que dió pie a esta sección del foro para ir aprendiendo cosas para optimizar y observo que estoy andando un camino que otros ya han andado antes. Me han hecho gracia dos comentarios de hace algún tiempo:

zx81 escribió:P.D.: Tras cada modificación es OBLIGATORIO validarla usando test, de corrección y de velocidad. Y tampoco vale hacer 500 modificaciones y probar, hay que validar poco a poco, literalmente tras cada modificación por pequeña que sea. A veces te sorprendes del impacto de pequeños cambios, para bien o para mal. Hay que ser muy metódico para hacer ese trabajo que, además, es aburrido.

¡¡ A.M.E.N. !! -grin Exactamente lo que he estoy viviendo estos últimos días. A veces se me enciende una bombilla, me paso media hora implementado una idea "revolucionaria", después mido tiempos y ná de ná: mi gozo en un pozo. En otras ocasiones, cambias el tipo de una variable en plan "me aburro no sé ya que hacer" e inexplicablemente (al menos para mi): !zas¡ 100 microsegundos mas rápido. Esto de rascar microsegundos está resultando adictivo y desesperante a la vez -grin

ackerman escribió:ackerman: Es imposible, pues, que un core de ESP32 pueda ejecutar un ciclo CPU completo y video en 20000 microsegundos.

El mismo @ackerman se desmintió a si mismo posteriormente y con resultados brillantes pero me ha hecho gracia leerlo :)

Seguiremos informando, ¡buen fin de semana a todos! -thumbup

Avatar de Usuario
dcrespo3d
Mensajes: 137
Registrado: 04 Nov 2020 08:51
Agradecido : 121 veces
Agradecimiento recibido: 154 veces

Re: Estreno nuevo subforo y avances emulador Spectrum dcrespo

Mensajepor dcrespo3d » 11 Jun 2022 09:49

Eremus escribió:
Las ultimas mediciones tras optimizar aquí y allá ya empiezan a pintar bien :)

CPU + VIDEO 18166 / CPU 11801 / VIDEO 6365

Cuando implemente el dibujado del borde, los tiempos subirán un poquillo pero creo que no será demasiado ni nada que no se pueda compensar posteriormente con algunas (o todas -grin) de las mejoras al core de @zx81 que @ackerman ha implementado en su fork.



Esto va teniendo una pinta estupenda. -thumbup

Una vez que tengas implementada la tarea CPU + vídeo, con la mejor optimización posible (cuanto más tiempo sobre, mejor) habría que incluir esperas para que el sonido del beeper suene lo mejor posible. Vamos, que la ejecución de cada instrución en el ciclo se realice en el momento más parecido posible a la máquina real. Cuando las tareas de CPU y vídeo estaban separadas, tenía en la tarea CPU unos delays (#define PER_INSTRUCTION_TIMING) que en realidad no hacian delay cada instrucción, sino cuando habían transcurrido un cierto número de tstates que eran ajustables, lo dejé a 50 y en esa situación iba bien. Pero sobraba mucho tiempo en la tarea de CPU y ahora en la tarea de CPU+vídeo va a sobrar menos... Si por lo menos se pudiera hacer una espera una vez por scanline (224 tstates), puede que estuviera bien, aunque el sonido PWM es muy sensible a las irregularidades en temporización.

Yo probé con la música introductoria del Arkanoid y con la demo pitstop / star tip 2 de Tim Follin. -harp
http://craigsretrocomputingpage.eu5.org ... xdump.html
DavidPrograma en YouTube, GitHub


Volver a “Desarrollo emuladores ESP32”

¿Quién está conectado?

Usuarios navegando por este Foro: Eremus y 1 invitado