ZX Spectrum llegó a Hacker News, pero el modo texto revela las concesiones de su ROM
- Aisha Washington

- hace 2 horas
- 14 min de lectura
El ZX Spectrum regresó a Hacker News mediante un recorrido por el sistema de 2026 que expone un conflicto oculto en su ROM de 16K. Imprimir un carácter puede ser sencillo. Crear una salida de texto fiable en código máquina exige comprender supuestos no documentados, variables del sistema mutables, atributos persistentes y rutas de entrada específicas del hardware.
Michael Martin publicó el recorrido por código máquina el 30 de mayo de 2026. La publicación continúa una exploración anterior de BASIC, pero hace más que traducir comandos conocidos a ensamblador Z80. Muestra dónde termina el cómodo entorno de programación de Sinclair y dónde comienza su firmware de estructura flexible.
Esa distinción da relevancia a la publicación más allá de la retroinformática. Las máquinas Commodore ofrecían tablas de salto KERNAL estables, mientras que MSX definía llamadas de firmware entre fabricantes. En cambio, el Spectrum animaba a los programadores a combinar unos pocos puntos de entrada de la ROM con acceso directo al estado del sistema. Este enfoque ahorraba capas de abstracción, pero trasladaba a los desarrolladores el trabajo de compatibilidad y depuración.
El resultado no es una función recién descubierta ni el anuncio de un producto moderno. Es un examen detallado de una antigua concesión de ingeniería. El Spectrum ponía primitivas útiles a disposición con muy poca memoria, pero nunca las convirtió en una plataforma limpia para código máquina.
Qué cambió realmente el recorrido por el sistema ZX Spectrum
La nueva aportación es una ruta conectada en código máquina que va de la salida de texto a los gráficos, la entrada y una pantalla completa en funcionamiento.
El Spectrum no ha adquirido de repente un modo texto. La publicación de Martin transforma la explicación disponible al reunir varios mecanismos dispersos en una secuencia práctica. Comienza con una rutina compacta de Hello World y luego recorre códigos de caracteres, controles de color, gráficos personalizados, limpieza de pantalla, lectura del teclado y entrada de joystick.
El primer paso usa RST $10, una entrada de reinicio de la ROM que imprime el carácter almacenado en el registro A del Z80. Un reinicio es una llamada compacta a una dirección fija de memoria baja. Antes de usarlo, el ejemplo escribe cero en TVFLAG en IY+2, dirigiendo la salida hacia el área principal de la pantalla.
Esa secuencia hace que la operación básica parezca casi moderna. Un programa carga un puntero a un mensaje, obtiene un byte, llama a la impresora y repite. Martin coloca el código en la dirección $7000, dejando espacio debajo para BASIC y conservando memoria utilizable en una máquina de 16K.
La simplicidad dura hasta que el texto requiere estado. La pantalla del Spectrum presenta normalmente 24 filas de 32 caracteres. Su firmware divide esas filas en una ventana superior de 22 líneas y una ventana inferior de dos líneas utilizada para edición y mensajes de estado. Las especificaciones de pantalla originales de Sinclair confirman esa división y describen una pantalla de 256 por 192 píxeles.
La máquina no cuenta con hardware de caracteres independiente, comparable al de un terminal convencional. Su ROM dibuja un glifo de 8 por 8 en la memoria de mapa de bits y después escribe la información de color para la celda correspondiente. Esto significa que la salida de texto ya depende de la disposición gráfica, los atributos actuales, la posición del cursor y el canal de salida seleccionado.
Martin amplía después la ruta con 16 caracteres semigráficos predefinidos y gráficos definidos por el usuario. Los semigráficos dividen una celda de carácter en bloques, permitiendo que formas simples pasen por la impresora de texto ordinaria. Los gráficos definidos por el usuario ocupan códigos de carácter a partir de $90, con sus datos de mapa de bits ubicados mediante el puntero del sistema UDG.
El ejemplo final de la publicación combina estas capacidades en un banner de colores con una imagen personalizada de un paraguas. Carga cuatro definiciones de caracteres, emite bytes de control en línea, espera una entrada y restaura la pantalla. Martin informa que el paquete de código máquina ocupa menos de la mitad que su versión anterior en BASIC, incluso tras incluir su cargador y cabecera de cinta.
Esa comparación es la verdadera recompensa del evento. La publicación no se limita a presentar direcciones aisladas. Demuestra que la ROM del Spectrum puede funcionar como un marco de aplicación compacto, siempre que el programador acepte la responsabilidad de su estado oculto.
Por qué una audiencia de Hacker News sigue interesándose por esta ROM
El Spectrum comprime un problema de sistemas conocido en una máquina lo bastante pequeña como para comprenderla casi por completo.
El artículo llegó a Hacker News porque trata el hardware retro como un sistema de software inspeccionable. Cada operación importante tiene una ruta visible. Un carácter pasa por una entrada fija de la ROM, lee un glifo, toca la memoria de mapa de bits, aplica un byte de atributo y avanza un cursor representado en el estado del sistema.
Los desarrolladores modernos se encuentran con las mismas categorías de problemas tras interfaces mucho más grandes. Las bibliotecas conservan configuración. Los flujos de salida tienen estado. La compatibilidad depende de comportamientos que la documentación quizá no promete. Las abstracciones de hardware exponen vías de escape cuando las interfaces normales resultan demasiado limitadas.
En el Spectrum, esos problemas caben dentro de un espacio de direcciones Z80. El modelo original utilizaba un procesador Z80A a 3,5 MHz, una ROM de 16K y 16K o 48K de RAM. Estas limitaciones hacen visible cada abstracción en el mapa de memoria.
La pantalla es especialmente instructiva. Una pantalla Spectrum estándar ocupa 6.912 bytes, compuestos por un mapa de bits monocromo de 6.144 bytes y 768 bytes de atributos. Cada byte de atributo proporciona colores de primer plano y fondo, brillo y parpadeo para una celda de 8 por 8.
Ese diseño ahorraba memoria, pero vinculaba los píxeles cercanos a una misma elección de color. El conocido resultado es el choque de atributos, donde objetos de distintos colores no pueden atravesar la misma celda sin afectarse entre sí. La impresión de texto hereda esa arquitectura porque cada glifo termina en una de esas celdas.
El recorrido de Martin añade una segunda lección. Una interfaz documentada pequeña no crea necesariamente una plataforma de programación estable. El Spectrum ofrece una impresora de caracteres eficaz, pero los programas sofisticados también deben conocer direcciones de variables como ATTR-T, MASK-T, P-FLAG, SCR-CT y UDG.
El documento oficial de variables del sistema describe la memoria compartida utilizada por BASIC y las rutinas ROM. Llamar al firmware mientras se modifican directamente esos valores es eficiente, pero crea un acoplamiento estrecho. Un programa depende tanto de la rutina invocable como del estado interno que esa rutina espera.
Aquí es donde el Spectrum se diferencia de máquinas diseñadas en torno a límites de firmware más formales. El KERNAL de Commodore utilizaba vectores de salto fijos para servicios comunes. MSX estandarizaba llamadas para que el software pudiera dirigirse a máquinas de distintos fabricantes. La BIOS del IBM PC también establecía servicios invocables por encima del hardware, aunque los desarrolladores más tarde los eludieran para ganar velocidad.
El enfoque de Sinclair era menos formal. Funcionaba bien con BASIC porque Sinclair controlaba tanto el intérprete como la ROM. Los programadores de ensamblador recibían detalles útiles de implementación en vez de un amplio contrato de compatibilidad.
Esa concesión explica el interés continuo. El Spectrum ofrece un caso de estudio excepcionalmente claro sobre cómo una implementación interna se convierte en una interfaz pública. Una vez que los programadores crean software contra direcciones y particularidades, esos detalles se vuelven difíciles de cambiar, tanto si su diseñador pretendía ese resultado como si no.
El verdadero adversario es la conveniencia frente a la estabilidad
La ROM del Spectrum facilita los programas simples, pero cada atajo aumenta la dependencia de comportamientos específicos de la máquina.
El conflicto central no es el ZX Spectrum contra el Commodore 64. Es la conveniencia frente a la estabilidad dentro del propio Spectrum. El acceso directo al sistema reduce el tamaño del código y expone capacidades útiles. También hace que el software sea responsable de supuestos que un contrato de firmware más sólido habría contenido.
Consideremos los atributos de texto. Los códigos de carácter $10 a $17 controlan INK, PAPER, FLASH, BRIGHT, INVERSE, OVER, la colocación del cursor y la tabulación. Un programa puede incrustar esos bytes dentro de una cadena y luego enviar toda la secuencia mediante RST $10.
Es un mecanismo compacto. Se parece a las secuencias de escape de terminal, donde bytes no imprimibles modifican la interpretación del texto posterior. Permite que los mensajes transporten formato sin llamadas de dibujo independientes.
La parte sorprendente es la persistencia. Esos controles de código máquina no se restablecen después del equivalente a una instrucción PRINT de BASIC. Un retorno de carro tampoco restaura el estado anterior. Por tanto, un ayudante que suponga que el formato termina con una cadena puede cambiar todas las operaciones de impresión posteriores.
La ROM rastrea atributos temporales y permanentes mediante varias variables del sistema. ATTR-T contiene los ajustes actuales de color, brillo y parpadeo. MASK-T determina qué bits deben permanecer sin cambios. Sus equivalentes permanentes influyen en la limpieza de pantalla y establecen valores predeterminados.
Esta división funciona porque BASIC la gestiona como parte de una operación de lenguaje mayor. El código ensamblador entra por debajo de esa capa. Debe reproducir el comportamiento de preparación y limpieza que BASIC proporciona normalmente.
La limpieza de pantalla revela la misma tensión. Llamar a la rutina CLS de la ROM limpia la pantalla, pero Martin señala que también redirige la salida posterior a la ventana inferior. No coordina por completo el borde de la pantalla con las áreas superior e inferior.
Su ayudante clrto repara ese comportamiento. Establece atributos permanentes, deriva el color del borde, limpia máscaras y banderas de modo, invoca CLS y después abre el canal dos para la pantalla superior. Una operación supuestamente básica se convierte en un pequeño protocolo de restauración de estado.
La rutina CHAN-OPEN en $1601 demuestra por qué la ROM sigue siendo útil. Abrir un canal es más claro que simplemente modificar una bandera. Sin embargo, el programa todavía necesita escrituras directas en variables y una instrucción de salida al puerto $FE. El acceso al firmware y al hardware sigue entrelazado.
Esta combinación puede ser productiva en un objetivo fijo. Evita duplicar el rasterizador de caracteres y la gestión del cursor de la ROM. Un desarrollador obtiene texto legible, controles de color, comportamiento de ventanas y glifos personalizados sin escribir cada rutina de píxeles.
El coste aparece cuando cambia el objetivo. Martin destaca el Timex Sinclair 2068, cuya ROM incompatible perjudicó la compatibilidad del software Spectrum en Estados Unidos. Los programas que dependían de rutinas fijas o disposiciones del sistema no podían asumir un comportamiento equivalente.
Una interfaz de programación de aplicaciones convencional separa el comportamiento admitido de la organización interna. El entorno de ensamblador del Spectrum ofrece solo una versión parcial de ese límite. Sus llamadas ROM son atractivas porque ya están presentes, pero el contrato circundante es reconstruido en parte por los desarrolladores.
Por eso el recorrido importa más que otro ejemplo de Hello World. Hace explícito el contrato oculto. El código documenta qué estado debe establecerse, qué rutinas lo alteran y qué valores necesitan restaurarse después.
El modo texto es en realidad un mapa de bits y una máquina de estados
Llamarlo modo texto es una abreviatura útil, pero la implementación es un renderizador de mapa de bits gobernado por estado mutable compartido.
La expresión «modo texto» suele sugerir celdas de caracteres dedicadas almacenadas como códigos de carácter. El hardware recupera un glifo para cada código y lo dibuja automáticamente. Cambiar una celda significa escribir un valor de carácter y quizá un valor de color.
El Spectrum original funciona de otro modo. El software invoca la impresora de la ROM, que representa los píxeles de los glifos en el mismo mapa de bits utilizado por los gráficos. Un área de atributos separada proporciona el color con resolución de celda de caracteres. La cuadrícula visual existe como una convención de programación, no como un búfer de texto completo en hardware.
Esta distinción explica varios mecanismos del recorrido de Martin. La ROM puede imprimir caracteres normales, gráficos de bloques y glifos definidos por el usuario mediante una sola ruta porque todos se convierten en patrones de 8 por 8 píxeles. La impresora no necesita saber si un glifo representa una letra o parte de un paraguas.
La parte alta del conjunto de caracteres del Spectrum respalda este enfoque. Los códigos $80 a $8F representan 16 combinaciones de bloques. Los códigos que comienzan en $90 direccionan gráficos definidos por el usuario. Los códigos posteriores codifican palabras clave de BASIC, lo que permite al intérprete almacenar comandos de forma compacta.
Los gráficos personalizados dependen de la indirección. La variable de sistema UDG apunta hacia los mapas de bits definidos por el usuario que están activos. Cada carácter ocupa ocho bytes, uno por cada fila. El ejemplo de Martin copia 32 bytes en esa área para definir cuatro piezas contiguas del paraguas.
Esa indirección es una abstracción modesta pero importante. La rutina de dibujo no requiere una única dirección de gráficos codificada de forma rígida. Un programa puede descubrir el área activa a través del puntero y después reemplazar las formas. El comportamiento se parece a un atlas de fuentes configurable a una escala mucho menor.
El color sigue basándose en celdas. Un byte de atributo asigna un color de tinta, un color de papel, un bit de brillo y un bit de parpadeo. Los píxeles individuales determinan si la celda muestra tinta o papel, pero no pueden elegir colores no relacionados.
Este diseño que ahorra memoria convierte los controles de formato en operaciones sobre el estado y la memoria de pantalla. Cuando la ROM imprime un carácter, consulta ATTR-T y MASK-T, escribe los píxeles y actualiza la celda de atributo. Las opciones de tinta o papel transparentes funcionan enmascarando campos seleccionados en lugar de sustituir el byte completo.
El desensamblado de la ROM sigue siendo valioso porque expone las rutas detrás de estos efectos. Ese material puede verificar qué cambia realmente un punto de entrada, especialmente cuando un programa depende de comportamientos que van más allá de la descripción superficial de un manual.
El estado compartido también provoca fallos sutiles. El primer bucle de impresión de Martin utiliza cero como terminador de cadena. Eso funciona hasta que cero se convierte en un dato significativo. El banner terminado necesita imprimir argumentos de control cuyo valor es cero, incluidos ajustes de papel y brillo.
Por ello, el bucle revisado utiliza $FF como centinela. Ese byte representa la palabra clave de BASIC COPY, que el banner no imprimirá. El cambio es pequeño, pero ilustra un problema general de protocolo: un terminador dentro de la propia banda falla cuando el formato de datos se amplía para incluir ese valor.
El mismo problema aparece en protocolos de red, formatos de archivo, flujos de comandos y bibliotecas de serialización. Un byte solo es seguro como delimitador mientras la carga útil lo excluya. Cuando los datos de control y los datos de visualización comparten un mismo flujo, el encuadre merece un diseño explícito.
Esa es la lección moderna más potente del artículo. Los límites de la máquina son antiguos, pero sus modos de fallo siguen vigentes. El estado compartido, los efectos secundarios no documentados, los valores de byte sobrecargados y las estrechas suposiciones de compatibilidad aún dan forma a los sistemas de software.
La entrada completa la disyuntiva del firmware
La gestión del teclado y del joystick muestra el mismo patrón que la salida de texto: usar el firmware cuando su política ayuda y sortearlo cuando importa el control directo.
El recorrido de Martin pasa de la salida de pantalla a la entrada de teclado porque un sistema de texto útil necesita interacción. El Spectrum vuelve a ofrecer dos rutas. Los programas pueden consumir el estado del teclado preparado por la ROM o leer directamente los puertos de hardware.
La ruta de firmware depende de la interrupción de trama de la máquina. Una interrupción es una transferencia activada por hardware hacia una rutina de servicio. En cada trama de vídeo, el controlador del Spectrum actualiza su temporizador FRAMES y explora la matriz de teclado.
Cuando encuentra una tecla, el controlador decodifica esa entrada y almacena un carácter en LAST-K. También activa el bit cinco de la variable de sistema FLAGS. La rutina getkey de Martin espera con la instrucción Z80 HALT, prueba la bandera, recupera el carácter, borra la bandera y retorna.
Usar HALT es importante. El bucle no tiene nada útil que hacer hasta que el controlador de interrupciones realiza otra exploración del teclado. Esperar esa interrupción evita leer repetidamente una bandera sin cambios a la máxima velocidad del procesador.
Esta ruta ofrece interpretación en vez de estado eléctrico sin procesar. La ROM entiende las combinaciones de teclado y las asigna a caracteres. Un programa puede aceptar texto sin reproducir el decodificador de teclado.
La entrada directa cambia esa comodidad por inmediatez. El teclado del Spectrum está organizado como una matriz a la que se accede mediante puertos de E/S. Seleccionar una fila y comprobar los bits devueltos revela qué teclas están pulsadas en ese momento.
El Z80 introduce una particularidad histórica. Algunas instrucciones de entrada y salida parecen exponer una dirección de puerto de ocho bits, pero IN A,(C) y OUT (C),A colocan el registro BC completo en el bus de direcciones. Sinclair aprovechó ese comportamiento al diseñar su interfaz de hardware.
El ejemplo de Martin comprueba la tecla A mediante el valor de puerto $FDFE. Ese código no espera a que la ROM traduzca una pulsación. Consulta al hardware por una posición de la matriz, lo que resulta útil para juegos que necesitan un estado direccional continuo.
El joystick Kempston es más sencillo. Utiliza el puerto $1F, donde los bits representan direcciones y el botón de disparo. El lector de Martin traduce ese campo de bits en deltas horizontal y vertical, además de un valor de disparo.
Estas opciones muestran por qué los programadores sortean abstracciones incluso cuando existe una. La entrada de teclado mediante firmware es adecuada para introducir texto o esperar una orden. Las lecturas directas de puertos son mejores para movimientos simultáneos, baja latencia y comprobaciones repetidas de estado.
El coste es la portabilidad. Una rutina vinculada a la matriz de teclado del Spectrum presupone la disposición eléctrica de la máquina. Un lector Kempston presupone esa interfaz concreta. Los emuladores deben reproducir esos comportamientos, mientras que el hardware alternativo o los estándares de joystick requieren código diferente.
Martin también señala inconsistencias relacionadas con teclas de mayúsculas sintéticas en emuladores. Es un ángulo escéptico útil. Una rutina técnicamente precisa aún puede comportarse de forma distinta cuando la implementación circundante interpreta la entrada del anfitrión de otra manera.
La aparición en Hacker News no debe confundirse con una verificación amplia de cada emulador o variante del Spectrum. La publicación enlazada recibió una respuesta modesta y ninguna discusión registrada en la instantánea proporcionada. El valor técnico procede de la ruta de código reproducible, no del consenso colectivo.
Por tanto, los lectores deberían separar tres niveles de afirmación. La documentación original de Sinclair establece las capacidades previstas de la máquina. El análisis de la ROM revela el comportamiento de implementación. Los ejemplos de Martin demuestran una vía de desarrollo que funciona, pero no garantizan resultados idénticos en cada clon, revisión de ROM, interfaz o emulador.
Qué deberían vigilar los desarrolladores tras el pico de Hacker News
La siguiente prueba es si este recorrido se convierte en infraestructura técnica duradera en lugar de un enlace efímero.
La primera señal es la continuación del recorrido por el sistema. Martin termina con una carencia clara: los ejemplos pueden reproducir la pantalla principal, la entrada y la animación necesarias para una versión en código máquina del juego anterior, pero el sonido y su pantalla de título siguen sin resolverse. Una continuación que aborde gráficos o audio mostraría si el mismo método escala más allá de la salida orientada a caracteres.
La segunda señal es la reproducibilidad entre objetivos. Los desarrolladores deberían probar los ejemplos en hardware original de 48K, modelos posteriores de Spectrum, emuladores comunes y variantes de ROM. Una salida coincidente reforzaría la idea de tratar estas rutinas como una capa práctica de compatibilidad. Las divergencias identificarían dónde el acceso directo al estado supera la estabilidad de las llamadas a la ROM.
La tercera señal es si el código se vuelve más fácil de inspeccionar y reutilizar. Un ejemplo descargable, un proceso de compilación documentado, una imagen de prueba fija o la automatización de un emulador convertirían el artículo en una referencia ejecutable. Martin ya nombra el ensamblador, la herramienta de empaquetado en cinta y el emulador FUSE utilizados para el flujo inicial de Hello World. Preservar esas dependencias importa tanto como preservar el listado de ensamblador.
También existe una cuestión más amplia de documentación. Las plataformas retro suelen tener información abundante pero una autoridad fragmentada. Los manuales describen el comportamiento previsto, los desensamblados exponen los detalles internos, las referencias de la comunidad corrigen errores y los tutoriales modernos conectan las piezas. Una guía de plataforma útil puede reducir esa fragmentación si distingue claramente los contratos documentados de las peculiaridades observadas.
Los desarrolladores que sigan la historia deberían resistirse a convertir un ejemplo elegante en una regla universal. Las llamadas directas a la ROM pueden ahorrar memoria y esfuerzo de desarrollo. El acceso directo al hardware puede mejorar la capacidad de respuesta. Ninguno garantiza compatibilidad fuera del entorno exacto donde fue probado.
Esa incertidumbre forma parte del valor. El ZX Spectrum permite rastrear fallos a través de una pila completa, desde un byte de cadena hasta una rutina de ROM, una variable de sistema, una dirección de memoria y una celda de pantalla. Pocos sistemas modernos permiten ese nivel de inspección.
La siguiente acción más útil es sencilla: reproduce el banner, cambia una suposición y observa qué se rompe. Mueve el código, altera el terminador, deja activo un atributo, selecciona el canal equivocado o prueba otra ROM. El momento de Hacker News pasará, pero esos experimentos preservan la lección real: una interfaz se define tanto por su estado y efectos secundarios como por el punto de entrada al que llama un programador.


