CoreMach nació como efecto secundario de BareMach. Al intentar llevar las máquinas de BluMach a una Raspberry Pi sin sistema operativo, aparecieron muchas dependencias entre sus componentes. Separar la emulación de todo lo demás daba tanto trabajo que acabó siendo un proyecto aparte: CoreMach, el motor portable.
Qué quería separar
Una cosa es el ordenador que intento reproducir: su procesador, memoria y dispositivos. Otra es la aplicación desde la que lo utilizo: las ventanas, la selección de archivos o la forma de mostrar la imagen y recibir las teclas.
La idea de CoreMach es tener el motor por un lado y poder usarlo desde distintos sitios: una versión portable de BluMach en el escritorio, con su catálogo y su configuración, y BareMach en la Raspberry Pi. Cada uno se encarga de mostrar la imagen, leer el teclado y acceder a los discos.
Que sea «portable» no quiere decir que funcione en cualquier sitio solo con compilarlo: cada destino hay que integrarlo y probarlo.
Las máquinas de prueba
Para probarlo de verdad necesitaba una máquina completa, y la primera fue el PCS 86, la misma que acabó arrancando en la Pi.
Más adelante también llegó el trabajo del PCS 286 en CoreMach. El 27 de septiembre, con su BIOS 1.42, arrancó DOS 3.30a desde disquete, y un archivo que copié desde DOS seguía ahí al cerrar y volver a abrir la imagen del disco. Pero el Customer Test todavía fallaba y el ATA estaba pendiente. Y es lento: en mis pruebas, el 286 de CoreMach gasta unas siete veces más CPU que el de BluMach y no llega a velocidad real ni en un x86 actual, así que en la Raspberry Pi, de momento, ni pensarlo. De «PCS 286 terminado», nada todavía.
Por qué lo rescato ahora
Rescato hoy esta historia porque, al final, este motor va a tener otra utilidad. BluMach arrastra una limitación heredada: es un emulador de x86 y, por la forma acoplada en la que está desarrollado, no admite otras plataformas. Eso no quiere decir que esté mal; resuelve muy bien el problema para el que se pensó.
El problema es que durante mucho tiempo el x86 se ha apropiado del término «ordenador personal» (Personal Computer), cuando en los setenta, ochenta y noventa hubo muchas máquinas que no eran x86. Y hoy el dominio del x86 se puede acabar.
BluMach y CoreMach, pieza a pieza
Con el PCS 86 se ve la diferencia. Los dos esquemas tienen la misma forma y las mismas piezas; lo que cambia es cómo se conectan. En BluMach, la interfaz y todos los dispositivos tiran del mismo estado global, y tocar una pieza obliga a arrastrar las demás:
En CoreMach, cada capa habla solo con la de al lado. La máquina es una composición de componentes, cada uno con su propio estado, y la interfaz se puede cambiar sin tocar el motor:
En resumen:
| Aspecto | BluMach | CoreMach |
|---|---|---|
| Organización | Heredada de PCem: CPU, dispositivos, configuración e interfaz comparten código. | Por capas: componentes, máquinas completas, motor e interfaz. |
| Estado | Mucho estado global: la CPU actual, el mapa de puertos, los temporizadores… | Cada máquina tiene su propia CPU, sus dispositivos, sus buses y su tiempo. Así es fácil aislarla y probarla. |
| Tiempo | Ligado a los contadores de la CPU heredados de PCem. | Una línea de tiempo común; la CPU y cada dispositivo van a su propia frecuencia, guardada como fracción exacta (el PIT va a 14,31818 / 12 MHz). |
| Componentes | Se enganchan con las funciones y tablas globales de PCem. | Cada componente declara lo que necesita (memoria, puertos, interrupciones, reloj) y la máquina se lo conecta. |
| Interfaz y plataforma | Una sola aplicación, con todas las dependencias de 86Box: Qt, sonido, red… | Motor C11 que puede compilarse sin Qt ni ventanas. Qt solo se usa si se quiere ventana. |
| Cobertura | Casi todo el hardware de 86Box, más lo añadido en BluMach. | Mucho menos: PCS 86, M15 y PCS 286, todavía en validación. El M10 está en camino. |
| Coste | La emulación corre en un hilo; el sonido y la red usan otros. Su V30 también simula el bus ciclo a ciclo. | Todo el motor corre en un solo hilo. Con la V30 y el 8088 gasta lo mismo o menos que BluMach; con el 286, unas siete veces más. |
Lo que he aprendido
Al separar el motor tienes que decidir cosas que antes estaban repartidas por todo el programa: quién hace avanzar el tiempo emulado, cómo hablan los dispositivos entre sí y qué pasa al reiniciar una máquina o cambiar un disco.
Probar cada componente por separado ayuda a encontrar fallos, pero que cada pieza funcione no quiere decir que funcione la máquina entera. Lo bueno es que ahora puedo probar la máquina completa fácilmente, sin arrastrar media aplicación.
CoreMach sigue en desarrollo. Mi idea era desecharlo, porque lo monté para la Raspberry Pi, pero ahora veo que va a ser muy útil para montar máquinas con arquitectura no x86, de Olivetti y de otras marcas. Solo en Olivetti hay unas cuantas con bastante documentación: el M10, un portátil con un 80C85; el M20, con un Zilog Z8000; o los Prodest PC128 y PC128S, que pese al nombre no tienen nada que ver: el primero es un Thomson MO6 con un 6809, y el segundo, un BBC Master Compact con un derivado del 6502. Da una idea de lo que se puede crear.
Lo próximo: el M10, y BluMach con dos motores
La siguiente máquina será el Olivetti M10, un portátil con un 80C85. Todavía no está terminado y tendrá su propia noticia.
Con el M10 llega además un cambio importante: BluMach empezará a usar CoreMach. A partir de ahí, BluMach tendrá dos motores de emulación: el heredado de 86Box para los PC x86 y CoreMach para las máquinas de otras arquitecturas. Ese es, al final, el sentido de haber desacoplado el motor.
El código está en GitHub: CoreMach y BluMach. BareMach todavía es privado; lo enlazaré cuando lo publique.
Fuentes y licencias
CoreMach no parte de cero. Este es el origen de cada parte, tal como lo anota el propio repositorio en provenance/components.json:
- Base: CoreMach se extrajo de BluMach, que es una versión modificada de 86Box, que a su vez viene de PCem. Todo se distribuye bajo GPL-2.0 o posterior, y cada archivo conserva los avisos de copyright y los autores originales.
- 8088 y V30: reescritura del intérprete heredado de 86Box, que a su vez es en gran parte un port de XTCE, el emulador de Andrew Jenner (reenigne), con trabajo de Miran Grča.
- 80286: escrito en su mayor parte de nuevo a partir de la documentación de Intel (referencias 210760-002 y 210498-005, y el manual de programación del 80286/80287 de 1987). El arranque y el reinicio derivan del código de BluMach. Para comprobarlo se usan las pruebas de SingleStepTests/80286, de Daniel Balsom (licencia MIT).
- Periféricos: el DMA 8237, el PIC 8259, el PIT 8253 y el vídeo PVGA1A derivan del código de BluMach y 86Box, contrastados con las hojas de datos de Intel y con el manual técnico del IBM PC AT. El controlador XTA deriva de un archivo de BluMach con licencia BSD-3-Clause (Fred N. van Kempen).
- 8085 (para el M10, en desarrollo): sale del modo 8080 de la propia V30 de CoreMach, completado con el Microprocessor Data Book de OKI (1986).
- IA: buena parte de este trabajo de reescritura lo hice con ayuda de IA.
- Esquemas y medidas: los esquemas los he hecho a partir del código de los dos repositorios. Las comparaciones de consumo las medí ejecutando el mismo bucle sintético en los dos emuladores, en un x86 actual: dan una idea, no son un banco de pruebas completo.
No se distribuye ninguna BIOS, ROM ni imagen de disco. Olivetti y los nombres de sus máquinas son marcas de sus propietarios; este proyecto no está afiliado a Olivetti ni a 86Box.