En la anterior entrega (FPS con BIOS), vimos el funcionamiento de los servicios de BIOS. Lo que hoy haremos será exactamente lo mismo, pero usando las bibliotecas bibliotecas gráficas del compilador, en nuestro caso graph.lib de Watcom C/C++, es decir, como nos enseñarían a hacerlo, incluso en la universidad.
El código tiene un aspecto bastante distinto. En vez de BIOS, usamos _setvideomode para asignar el modo gráfico, _remappalette para fijar la paleta de colores y la combinación de kbhit y getch para comprobar el estado del teclado. Sin embargo a nivel estructural es equivalente, y el dibujo se hace también sobre píxeles individuales, que requieren para cada uno de ellos una llamada a _setcolor y _setpixel.
Obtenemos los siguientes resultados:
– graph.lib: 17 KPixeles/segundo (0,26 FPS).
Que comparado con los resultados de los ejemplos anteriores, nos dan el peor rendimiento de todos:
– BIOS: 18 KPixeles/segundo (0,28 FPS).
– Acceso al hardware: 5.952 KPíxeles/segundo (93 FPS).
Vemos que estamos obteniendo un desempeño todavía peor que usando la BIOS. Es lógico, ya que la mayoría de lenguajes implementan gran parte de sus librerías usando los servicios de BIOS.
¿Qué ventajas obtenemos entonces? Es sencillo, las primitivas gráficas del compilador, disponen de funcionalidades listas para ser usadas, desde dibujo de lineas, que no es algo trivial, hasta gráficos, fuentes, polígonos, etc. Por tanto nos ahorran trabajo y errores, en comparación con desarrollarlas nosotros. Por otro lado,y al igual que con la BIOS, contamos con soporte universal de todos los modos de pantallas que se soporten, sin necesidad de modificar el código, y lo que es más importante, soporte de diferentes plataformas.
#include
#include
Pero no acabamos aquí, porque como ya vimos en portabilidad, un conocimiento interno de como funcionan nuestras herramientas, puede ayudarnos enormemente. En este caso concreto a simplificar el código, y mejorar el rendimiento.
La mayoría de compiladores de C, pero también de otros lenguajes como Basic o Pascal, nos ofrecen funciones de manejo de sprites, en nuestro caso es _putimage, que tiene por finalidad dibujar una imagen en la pantalla. Desconozco el motivo, pero tanto la mencionada _putimage, como las implementaciones de PUT en Basic almacenan el bloque a dibujar con dos añadidos al principio, el ancho y el alto en píxeles del bloque. Así a la hora de dibujarlo, basta con especificar las coordenadas X e Y.
Modificamos nuestro ejemplo, e incluimos en el array gacPerin dos enteros cortos de 16 bits con sus dimensiones, antes de los datos propiamente dichos, y estamos listos.
#include
#include
Los resultados:
- graph.lib (_putimage): 2.368 KPixeles/segundo (37 FPS).
Y recopilando las cifras anteriores:
- graph.lib (_setpixel): 17 KPixeles/segundo (0,26 FPS).
- BIOS: 18 KPixeles/segundo (0,28 FPS).
- Acceso al hardware: 5.952 KPíxeles/segundo (93 FPS).
Es decir, hemos conseguido obtener un rendimiento del orden de 2,5 veces más lento que accediendo al hardware directamente, y de 150 veces más rápido que usando _setpixel. No es nada despreciable, si consideramos que _putimage no está limitado a operar con la pantalla entera como hacíamos al usar memcpy, sino que es capaz de dibujar cualquier sprite rectangular, incluso con operaciones lógicas a la hora de volcar los píxeles individuales.
La conclusión de este artículo, y de momento de toda la saga, es que más importante que las técnicas y herramientas que se usen, es el conocimiento interno de las mismas, pudiendo enfocarnos hacia más simplicidad, flexibilidad, rendimiento, o tamaño, según nos convenga en cada caso.
Podéis descargar los dos códigos fuente y ejecutables del artículo aquí (145 Kb. en formato ZIP).
no he usado a profundidad open watcom, salvo para hacer algunos programas, pero hasta donde tengo entendido las funciones de conio.h y graph.h (por ejemplo para iniciar el modo de video) eran de borland y había problemas al portarlas a otros compiladores. ¿Se pueden usar libremente en open watcom?, ¿son otras funciones?, es que me parece interesante.
Efectivamente conio.h fue un «invento» de Borland de manera que el resto de competidores, lo implementaron o no. Por ejemplo en Watcom, igual que en Microsoft, el soporte es parcial.
Sin embargo graph.h es probablemente mucho más potente en Watcom, claro que no es una réplica y algunas cosas funcionan un poco diferentes.
Lo que si te puedo decir, es que en los momentos de la pugna Microsoft/Borland contra Watcom, se detectó que el código generado por Watcom, era casi el doble de rápido. Por supuesto ahora, además Openwatcom es gratuito, y de código abierto, otra ventaja más para apostar por él.
Si tienes curiosidad, tienes la documentación completa de la libería de C, disponible aquí: http://www.openwatcom.org/ftp/manuals/current/clib.pdf
¡Dale un voto de confianza Manuel! Puede que al principio te resulte extraño el cambio, pero vale la pena.
ok, en su momento lo probaré, gracias.