Lithographica

Un cuaderno más de Juan Antonio Fernández Madrigal

Las imágenes del ZX Spectrum

Julio25/2011

Pedazo de entrada retro-friqui que os espera ;)

De vez en cuando me da la nostalgia ochentera, habitualmente coincidiendo con la cercanía a las vacaciones de verano (no me preguntéis por qué), y con bastante probabilidad me da en lo relacionado con esa maravillosa máquina, el ZX Spectrum, con el que se nos descubrió un nuevo mundo a tantos niños y no tan niños de la época.

Normalmente la cosa se resuelve visitando una vez más WorldOfSpectrum, echando unas partidillas a mis adorados Xeno y Manic Miner, y pensando por enésima vez por qué aquel emulador de Spectrum que me hice en 1991 para un i286 no me dio por hacerlo diez años después, que seguro que podía haberlo terminado mejor (con mucha más documentación disponible de la que yo tuve); ahora podría estar incluido en la lista de emuladores.

En fin. Esta vez me ha dado la picá por otro lado. No sé cómo he acabado pensando que podría ser curiosón el poder convertir imágenes bitmap a la apariencia que tenían las imágenes en el ZX Spectrum, y, ya puestos, hacer un plug-in para el programa de diseño gráfico GIMP que haga esa transformación. Hay alguna utilidad por ahí relacionada con la conversión de imágenes del Spectrum, pero no algo como lo que propongo en forma de plug-in de GIMP. Así que, ni corto ni perezoso, me he puesto a la tarea :)

Las imágenes del ZX Spectrum en su modo gráfico original, es decir, sin usar hardware/software especial que consiguiera incrementar la resolución, eran bitmaps de 256×192 píxeles, con el píxel 0,0 en la esquina inferior izquierda si mal no recuerdo (estoy escribiendo de memoria). Estos píxeles no se podían poner a ningún color concreto, sólo a apagado (0) o encendido (1), lo que suponía 256×192/8=6144 bytes de información que estaban almacenados a partir de la dirección 16384 de la RAM, es decir, justo tras los primeros 16KB de la ROM del sistema.

El color era el verdadero meollo de la historia de los gráficos de Spectrum. La paleta del ZX (de la que ya hablamos por aquí) tenía 8 colores, algunos de los cuales se observan en la esquina inferior derecha de la carcasa de la foto de arriba. Si Sir Clive Sinclair hubiera querido que pudiéramos especificar uno de esos 8 colores por cada píxel del bitmap, a tres bits por píxel, hubiera gastado un total de 256x192x3/8=18432 bytes de memoria para la imagen de pantalla, en lugar de los 6144 del blanco y negro. Definitivamente, 18KB era algo prohibitivo para la época, especialmente teniendo en cuenta que la RAM del Spectrum era de 48KB: con esa capacidad gráfica sólo hubieran quedado 30KB para variables del sistema, programas del usuario y pila de la CPU. Pero mucho peor: hubiera habido bastantes problemas de rendimiento a la hora de que una CPU Z80A a 3.47MHz direccionara los píxeles y no digamos ya de que hiciera animación, por mucho que yo siga admirando a esa CPU.

La solución no pudo ser más ingeniosa, a la par que enrevesada a la hora de su uso posterior: dividamos los 256×192 píxeles en celdas de 64 píxeles cada una (de 8×8 píxeles, para ser exactos), y asignemos un byte extra a cada celda, llamado “atributo”, que indique el color que tienen los píxeles de esa celda que estén a 0 -píxeles de “papel”- y el que tienen los píxeles que estén a 1 -píxeles de “tinta”. Además, al dividir la imagen en celdas de 8×8 podemos montar un modo texto además del modo gráfico, con sus rutinas específicas: en cada celda se podrá dibujar un carácter, pudiendo tener en pantalla 24 líneas por 32 columnas de texto. Bondadoso que es el destino: si dedicamos 1 byte al atributo de cada celda, dado que especificar un color, ya sea el de tinta o el de papel, ocupa 3 bits, nos quedan todavía 2 bits libres para jugar. Uno de ellos se dedicó al “brillo”, y otro al “parpadeo”. El esquema final de un byte cualquiera de atributo quedó así:

Lo del brillo es otra genialidad: con ese bit a 1 cualquier atributo podía indicar que los colores de papel y tinta no vinieran de la paleta original, sino de otra que contenía los mismos colores pero con más brillo -excepto el negro, que era el mismo-, es decir, que con el bit de brillo prácticamente se duplicaban los colores disponibles en la pantalla, con la salvedad de que no se podía usar un color con brillo y otro sin brillo en la misma celda.

Lo del parpadeo tenía también su enjundia: con otro bit por celda se podía hacer que el color que en ésta estaba asignado a la tinta pasara a ser mostrado en los píxeles de papel, y viceversa, intermitentemente (con una frecuencia de 1Hz, si tampoco recuerdo mal), todo eso sin necesidad de que el programador cambiara nada en memoria, puesto que lo realizaba automáticamente la ULA (uncommitted logic array), la circuitería gráfica del Spectrum. Esto del parpadeo puede parecer una tontería de poca utilidad, pero imaginad qué pasa si relleno algunas celdas de la pantalla con todos sus píxeles en tinta, otras con todos sus píxeles en papel, y activo el parpadeo: puedo montarme un cartel -con poca resolución, eso sí- que va cambiando de apariencia intermitentemente, es decir, puedo tener dos imágenes que se turnan en pantalla alegremente.

Se puede ver precisamente este efecto del parpadeo a partir del segundo 10 del siguiente vídeo, grabado del juego ya mencionado Manic Miner. También se observa claramente el típico aspecto de los gráficos del ZX Spectrum. El pedazo de borde que rodea a la imagen de pantalla estaba en principio desperdiciado: sólo se podía poner a un color, aunque si variabas ese color lo suficientemente rápido, como por ejemplo hacía la ROM mientras cargaba un programa en memoria desde la cinta de cassette, podías conseguir efectos muy curiosos.

En resumen: tenemos 6144 bytes que guardan qué píxeles de la imagen son papel y cuáles son tinta, y además otros 768 bytes a continuación de éstos, correspondientes a las 768 celdas de 8×8 píxeles que hay en una imagen de 256×192 píxeles, los cuales definen los atributos de color. El total es 6912 bytes, casi 7KB, para toda la imagen (bueno, 3 bits más si contamos el color del borde ;P), lo cual es absolutamente óptimo en términos de tamaño en memoria, funcionalidad gráfica y potencia de procesamiento. El ZX Spectrum introdujo verdaderas genialidades para su época, y este modo gráfico, por muy ridículo que nos parezca hoy en día, fue una de ellas.

Respecto al plug-in de GIMP que he escrito para transformar el aspecto de cualquier bitmap al de una imagen del ZX Spectrum no hay tanto que contar… Es fácil hacer plug-ins para GIMP, especialmente sobre sistemas Linux (GIMP también tiene versiones para otros sistemas) y programando en C. Aquí hay un tutorial que demuestra lo sencilla de usar que es la API de GIMP: te da un entorno de ejecución bastante completo donde se puede acceder a la imagen en curso.

El plug-in requiere que la imagen original sea RGB (no lo he probado pero está supuestamente preparado para trabajar también con imágenes que tengan canal de transparencia). La resolución de ésta no importa, aunque para tener una experiencia cercana a la de un verdadero ZX Spectrum es interesante reducirla primero de tamaño, concretamente a 256 píxeles de ancho (el alto da bastante igual), antes de aplicar el filtro. El plug-in se instala a sí mismo en una nueva carpeta de filtros de GIMP llamada “ZX” y no requiere ningún parámetro antes de ejecutarse. Hace la conversión directamente sobre la imagen, y usa una paleta de colores que he comprobado que es bastante parecida a la original del ZX. Incluso lo he probado sobre capturas de pantalla de emuladores del Spectrum y he validado que no cambia su contenido.

El algoritmo tiene su intríngulis porque hay que tomar algunas decisiones a la hora de reducir la gama de colores de la imagen inicial. Para empezar, se trata cada celda de 8×8 de la imagen inicial por separado (pueden sobrar píxeles en los bordes si el tamaño de la imagen original no es múltiplo de 8; éstos se mostrarán en negro). Dentro de cada celda se calcula qué color de la paleta del ZX Spectrum es más cercano al color del píxel en la imagen original, usando para ello la distancia cartesiana en el espacio tridimensional de coordenadas RGB. Tras esa conversión de color se hace un histograma para ver qué color del Spectrum aparece más frecuentemente dentro de la celda, y también cuál es el segundo más frecuente. El primero será el de tinta y el segundo el de papel -esta elección es arbitraria. Todos los píxeles de la celda que no sean del color de tinta ni del de papel serán convertidos al color de esos dos que quede más cercano en el espacio RGB. Finalmente está la decisión sobre el brillo (el parpadeo no se trata). Si ambos colores de la celda tienen el mismo brillo no hay que hacer nada. Si no, hay que cambiar uno para que tenga el mismo brillo que el otro porque sólo está permitido tener los dos con brillo o los dos sin brillo. Si uno de ellos es negro se le cambia el brillo a ése para que coincida con el brillo del otro y ya está, ya que el negro con brillo es el mismo color que el negro sin brillo. Si no es el caso, se le cambia el brillo al color que sea menos frecuente en la celda, en nuestro caso al papel. Voilà :)

Obviamente, se puede enriquecer este algoritmo con muchísimas cosas, principalmente para tener en cuenta la imagen completa y no por celdas separadas, ya que esto podría mejorar mucho la apariencia final al tomar decisiones que dependieran de la distribución global de los colores. Esto lo dejo para cuando tenga ganas de escribir el paper “Back to eighties: a new approach to draw ZX Spectrum bitmaps from RGB images” y mandarlo a algún sitio donde me lo rechacen inmisericordemente por irrelevante XDD (lástima que no exista ninguna IEEE Transactions on Freak Stuff indexada para el currículum ;P).

En este enlace podéis descargar el código fuente del plug-in. No he tenido ningún cuidado con la estructura ni elegancia del programa (aunque está bastante documentado), así que no respondo si se os caen las pestañas pensando cómo he podido hacer tal guarrerida programatística. Era pa jugar un ratillo ;) Para instalarlo en una máquina con Linux sólo hay que instalar previamente la librería de desarrollo de GIMP (libgimp-dev, típicamente en los repositorios) y luego usar la herramienta “gimptool-2.0″ desde línea de comandos como se explica en el mismo código fuente del plug-in.

Aquí dejo algunos ejemplos de lo que se puede conseguir (el último está ligeramente manipulado ;P). Podéis darle al Ctrl+ varias veces en vuestro Firefox para apreciar mejor los detalles:









Los límites del software

Junio8/2011

The ideal [programming] library is small, fast, powerful, flexible, extensible, intuitive, universally available, well supported, free of use restrictions, and bug-free. It is also nonexistent.
—–
La librería [software] ideal es pequeña, rápida, potente, flexible, extensible, intuitiva en el uso, disponible para todas las plataformas, con un buen soporte, no tiene restricciones de uso y está libre de errores. También es inexistente.

More Effective C++ (Scott Meyers, 1996)

No sólo pasa en la industria del videojuego

Marzo22/2011

Tras pocos años en el mundo del desarrollo videojueguil, Menéndez descubrió que lo importante no era la creatividad ni la técnica, sino el negocio puro y duro. Vamos, que se dio de bruces contra la realidad.

Artículo sobre Paco Menéndez, uno de los creadores de videojuegos más importantes de la época del ZX Spectrum

Las bondades de MS-DOS

Marzo11/2011

Lo mejor que tenía MS-DOS desde el punto de vista de un programador era lo fácil que era saltárselo a todos los niveles y conectar tus programas directamente con la máquina, sin necesidad de aguantar sus ineficiencias, falta de estructura lógica y limitaciones.

La eterna crisis del software. A ver si va a ser la gente al final…

Marzo1/2011

He entrado en un nuevo puesto de trabajo de desarrollo de software y me he encontrado con que la gente aquí no sabe programar de una manera estructurada, encapsulada, con un diseño orientado a objetos que cumpla el principio abierto/cerrado y el de responsabilidad única; no aplican patrones de diseño (ni siquiera saben lo que son), no utilizan herencia ni interfaces; el código es un caos de parcheos, chapuzas y declaraciones de clases a las que ni siquiera les puedes poner un nombre y una descripción concreta porque simplemente las usan como punto de entrada a una ristra de funciones sin estado y propósito concretos. Dicen que soy quisquilloso y “especialito” porque estoy todo el dia intentando convencerles de todos los problemas inherentes a hacer las cosas así (mantenibilidad, trazabilidad del rendimiento, menos posiblidades de bugs, flexibilidad y facilidad ante los cambios que puedan surguir, etc). Pero dicen que no tengo razón y que lo que yo propongo sólo sirve para tardar más en programar una aplicación (y el jefazo que les podría obligar les da la razón).

Copiado de Barrapunto

Yo esto lo vengo viendo de cerca desde hace tantos años que ya ni me sorprende, pero no debería acostumbrarme, porque no es de recibo. Pasa por pensar que si alguien sabe juntar instrucciones en algún lenguaje de programación sabe programar. Pues no. Ni de lejos. Y, en el fondo, viene de que hacer las cosas rápido -para hacer muchas, que es lo que mola- significa normalmente hacer las cosas bastante mal. Que algo te cueste hacerlo bien más tiempo del que a ti te gustaría o del que te llevaría si lo hicieras a vuelapluma no es malo, ni indeseable, sino lo natural. El esfuerzo entrena el autocontrol y pone las bases para crecer como persona.

Sin cosas que se hagan con el esfuerzo y el cuidado que merecen, el largo plazo, y por tanto cualquier desarrollo medianamente complejo, quedan completamente fuera de nuestro alcance. Se hace así imposible avanzar y superar lo que se hizo antes, porque siempre se están volviendo a repetir los mismos errores sobre las mismas cosas. O corrigiendo los que no se tuvo el cuidado de no cometer.

Pero vaya, está claro que seguiremos así por los siglos en ciertos sitios… Parece que nos encanta ir siempre a rebufo de los que verdaderamente se preocupan por hacer bien su trabajo, quedarnos permanentemente por debajo de nuestras posibilidades.

Para empezar bien la semana

Octubre25/2010

Nada mejor que unas risas a costa de los maravillosos comentarios escritos en su código por algunos programadores muy quemados (por lo visto un clásico, pero yo los descubrí hace unos días). Selecciono los que me han parecido mejores de la primera página del enlace original:


/**
* For the brave souls who get this far: You are the chosen ones,
* the valiant knights of programming who toil away, without rest,
* fixing our most awful code. To you, true saviors, kings of men,
* I say this: never gonna give you up, never gonna let you down,
* never gonna run around and desert you. Never gonna make you cry,
* never gonna say goodbye. Never gonna tell a lie and hurt you.
*/


//When I wrote this, only God and I understood what I was doing
//Now, God only knows


// I dedicate all this code, all my work, to my wife, Darlene, who will
// have to support me and our three children and the dog once it gets
// released into the public.


long john; // silver


#define TRUE FALSE //Happy debugging suckers


const int TEN=10; // As if the value of 10 will fluctuate...

Qué suerte: en todos sitios cuecen habas

Julio7/2010

It had struck me that the normal computer science courses [at University] did not cover enough basic material in low-level programming and electronics, which was necessary to support a career in real-time, embedded development. There had also been a continuing trend to separate the study of hardware from software, reducing students’ ability to understand the operational totality of microprocessor-based systems. [...] On the other side of the fence, electronic engineers scratched away at assembler spaguetti code, or naively marvelled at the irredeemable wonders of Basic.
—-
Me conmocionó el que los cursos habituales de informática en la Universidad [N.T.:británica en este caso] no cubrieran suficiente material básico acerca de la programación de bajo nivel y la electrónica, que era necesario para formarse en el desarrollo de sistemas de tiempo real empotrados. Había habido también una tendencia continuada a separar los estudios de hardware de los de software, reduciendo así la capacidad de los estudiantes para comprender en su totalidad los sistemas basados en microprocesadores. [...] En el otro lado, los ingenieros electrónicos escarbaban en código ensamblador “espagueti”, o se sorprendían ingenuamente de las imperdonables maravillas del Basic.

Rob Williams, autor de Real-Time Systems Development (2006)

El origen de la crisis del software

Julio1/2010

Aunque sea en el fondo, a pocos programadores les gusta reusar código: siempre le encuentras detallitos que te fastidian, cosas que no se adaptan del todo a tu problema, a la manera que tú tendrías de abordarlo o simplemente al estilo en el que tú haces las cosas; normalmente estás más dispuesto a gastar tiempo en hacerlo tú que a gastarlo en aprender cómo demonios se le ha ocurrido a otro hacerlo.

No es difícil de comprender: a un arquitecto le gusta hacerse su casa, a un pintor sus cuadros…

Regla sencilla (y bestia) para clasificar lenguajes de programación

Junio11/2010

Si no puedes traducir mentalmente cada una de sus sentencias a algún lenguaje ensamblador, no está hecho para programadores de verdad (de los pocos que quedan que son conscientes de que existe un hardware debajo haciendo todas las cositas).

Windows vs. Distribución de Linux

Mayo10/2010

Lo primero que echo de menos cuando uso un Windows (cualquiera) es el tiempo de arranque de una distribución de Linux (cualquiera), lo segundo el escritorio múltiple, lo tercero los repositorios de aplicaciones completamente gratis y plenamente funcionales, lo cuarto es lo superfluo del antivirus, lo quinto la miríada de herramientas para los programadores, lo sexto el poder, si quisiera, ponerme a entender por qué hace lo que hace, lo séptimo es lo rápidamente que encuentro las cosas entre los menús, lo octavo ya no me da tiempo a echarlo de menos porque me encuentro machacando el Windows con mi distribución de Linux favorita.

Por cierto, hete aquí el netbook/lector-electrónico-y-mucho-más con el flamante Ubuntu Lucid Lynx instalado (¿no es una monería) ?:

« Antiguas
  • Últimas lecturas:

  • Andanzas artísticas:

  • Criaturas:

  • Creative Commons License