La evaluación de la inteligencia artificial general y de los agentes autónomos de aprendizaje por refuerzo enfrenta un severo cuello de botella de cómputo. Los entornos de pruebas sintéticos modernos —construidos sobre motores como Unreal Engine 5, Unity o simuladores de robótica de alta fidelidad— exigen ingentes recursos de GPU simplemente para renderizar geometría visual y calcular física newtoniana. Si bien el fotorrealismo resulta indispensable en robótica de campo, introduce una sobrecarga prescindible cuando el objetivo es entrenar agentes en capacidades cognitivas fundamentales: navegación espacial, gestión de recursos a largo plazo, coordinación táctica y deducción abstracta.
Aquí entra **Play-dos**, un framework abierto de virtualización diseñado para reutilizar software MS-DOS de los años 90 como sandboxes deterministas de alto rendimiento para la investigación en aprendizaje automático. Al transformar aplicaciones x86 en modo real y modo protegido de 32 bits en canalizaciones de ejecución vectorizadas y *headless*, Play-dos elimina la sobrecarga visual de los entornos contemporáneos. A cambio, expone la lógica pura del juego, estados de memoria directos y *framebuffers* de baja latencia a los algoritmos actuales de aprendizaje por refuerzo (RL) y modelos de visión y lenguaje (VLM).
«`
+——————————————————————-+
| Python ML Agent |
| (Gymnasium / PyTorch / PettingZoo / VLM Agent) |
+———————————+———————————+
| Zero-Copy IPC / POSIX Shared Mem
+———————————v———————————+
| Play-dos C++ Core |
| +———————-+ +——————+ +————–+ |
| | Headless DOS Machine | | Memory Introspect| | Hook Engines | |
| | (16-bit / 32-bit DPMI| | (RAM Scanning) | | (INT 10/16h) | |
| +———————-+ +——————+ +————–+ |
+———————————+———————————+
| Register & Video Memory Hook
+———————————v———————————+
| Legacy DOS Title Binaries |
| (Doom, SimCity 2000, Civilization, X-COM) |
+———————————–+——————————-+
«`
—
La arquitectura de Play-dos: el modo real de 16 bits frente al aprendizaje profundo por refuerzo

Los sistemas operativos contemporáneos descartan la arquitectura clásica de interrupciones x86 y los modelos de memoria segmentada. Play-dos los implementa dentro de una capa de hipervisor aislada e instrumentada, derivada de la emulación modular de DOS y despojada de mezcla de audio, sincronización de sonido en tiempo real y protocolos de visualización física.
Emulación Headless y la capa de virtualización
Play-dos opera como un demonio C++ independiente acoplado directamente a la memoria del host mediante primitivas POSIX de memoria compartida (`shm_open`, `mmap`). A diferencia de los emuladores DOS orientados a consumo —diseñados para garantizar fidelidad audiovisual en monitores de escritorio—, Play-dos se ejecuta íntegramente en modo *headless*. El bucle de ejecución elimina los limitadores dinámicos de ciclos que históricamente sincronizaban los juegos a frecuencias de 4,77 MHz, 33 MHz o 66 MHz.
Al desvincularse del refresco vertical del monitor del host (bloqueo VSync a 60 Hz) y de las interrupciones del DAC de audio, el motor de emulación avanza a la velocidad máxima que permita la CPU. Un único núcleo estándar AMD EPYC o Intel Xeon procesa miles de ciclos virtuales de CPU por milisegundo, permitiendo tasas de ejecución que superan los 15.000 fotogramas por segundo (FPS).
Extracción del framebuffer e inyección directa en memoria
Play-dos intercepta directamente el mapa de memoria virtualizada VGA/EGA. En el estándar VGA Modo 13h —la referencia gráfica predilecta en los títulos de los 90—, el búfer de pantalla físico reside en la dirección lineal `0x000A0000`.
En lugar de transferir este búfer a una canalización de composición OpenGL o Vulkan para generar ventanas en el sistema operativo, Play-dos lee la matriz directa de $320 times 200$ bytes. Cada byte mapea a una paleta dinámica de 8 bits indexada en registros de color RGB. El framework ejecuta tres operaciones directas:
1. **Desreferenciación de paleta**: Transforma la matriz de índices de 8 bits de $320 times 200$ en un tensor intercalado `uint8` con dimensiones `(200, 320, 3)` mediante instrucciones vectoriales SIMD.
2. **Transferencia IPC Zero-Copy**: Aloja el tensor sin procesar dentro de un búfer circular en memoria compartida, accesible por procesos externos de Python.
3. **Emulación de interrupciones**: Omite la interrupción de retorno vertical (INT 0x0A / IRQ 2), lo que permite a los bucles de renderizado del juego consolidar actualizaciones de pantalla instantáneamente sin bloquear las instrucciones de CPU.
En paralelo, las entradas del agente evitan las colas de eventos del sistema operativo anfitrión. Play-dos captura pulsaciones de teclas y movimientos del ratón inyectando *scancodes* directamente en el búfer circular de teclado de la BIOS Data Area (BDA) en las direcciones `0x0040:0x001E` a `0x0040:0x003D`, o disparando la interrupción por software `INT 0x16` dentro del núcleo virtual de la CPU.
«`
+————————————————————————-+
| Canalización de ingesta directa Modo 13h |
| |
| [VRAM 0xA0000] —-> [Traducción SIMD de paleta] —-> [Búfer compartido] |
| (320×200 @ 8-bit) (Indexado -> RGB empaquetado) (NumPy Zero-Copy)|
+————————————————————————-+
«`
—
Superioridad de los entornos DOS sobre los motores 3D modernos para el entrenamiento de IA
Los laboratorios de machine learning destinan presupuestos masivos a infraestructura en la nube para ejecutar simuladores modernos. Una sola instancia de un entorno Unreal Engine suele requerir una GPU Nvidia RTX 4090 o A100 dedicada para apenas alcanzar unos cientos de fotogramas por segundo. Play-dos altera drásticamente esta ecuación de recursos.
| Característica / Métrica | Motores 3D modernos (Unreal / Unity) | Arcade RL clásico (Atari 2600 vía ALE) | Entorno virtualizado Play-dos |
| :— | :— | :— | :— |
| **RAM por instancia** | 4 GB – 16 GB | ~15 MB | **8 MB – 32 MB** |
| **Dependencia de GPU** | Obligatoria (renderizado 3D) | Nula (nativo en CPU) | **Nula (emulación pura en CPU)** |
| **Rendimiento de ejecución** | 100 – 600 FPS por GPU | 3.000 – 6.000 FPS por núcleo | **10.000 – 25.000 FPS por núcleo** |
| **Complejidad de la tarea** | Alta carga visual, lógica básica | Baja carga visual, lógica reactiva simple | **Visual equilibrado, alta profundidad táctica/estratégica** |
| **Inspección de estado** | APIs complejas, telemetría pesada | Trivial (128 bytes de RAM) | **Directa (640 KB – 32 MB memoria plana)** |
| **Workers paralelos (Nodo 64 cores)**| 2 a 4 workers (límite por VRAM) | 64+ workers | **64 a 128 workers concurrentes** |
Determinismo, huella de memoria y eficiencia de cómputo
Los sistemas operativos actuales y los motores de juego complejos dependen de cálculos físicos multihilo, carga asíncrona de recursos y aritmética de punto flotante no determinista. Estos elementos introducen discrepancias mínimas entre iteraciones de entrenamiento que entorpecen la depuración y desestabilizan las políticas de aprendizaje por refuerzo.
DOS opera en un entorno monohilo con direccionamiento real. Cada instrucción se ejecuta en una secuencia estricta de ciclos. En Play-dos:
* La generación de números pseudoaleatorios en los juegos depende de generadores congruenciales lineales regidos por contadores de ciclos deterministas (como el pulso del temporizador DOS en `0x0040:0x006C`).
* El estado de ejecución íntegro —abarcando la memoria de MS-DOS, controladores cargados y el montículo (*heap*) del ejecutable— rara vez excede los 16 MB.
* La serialización de estado es inmediata: generar un punto de control (*checkpoint*) solo exige un `memcpy` de la RAM virtual asignada, reemplazando la serialización profunda de grafos de objetos típica de motores modernos.
Granularidad del espacio de estados frente a complejidad perceptiva
Los títulos de Atari 2600 (popularizados por Arcade Learning Environment) ofrecen mínima sobrecarga de procesamiento, pero su profundidad táctica es elemental. Videojuegos como *Pong*, *Breakout* o *Space Invaders* ponen a prueba reflejos inmediatos con horizontes de recompensa cortos; no permiten evaluar razonamiento secuencial multietapa.
El software para DOS de los años 90 representa el punto cúspide del diseño algorítmico estructurado:
* **Autómatas de estado complejos**: Juegos como *Civilization*, *SimCity 2000*, *Master of Orion* o *X-COM: UFO Defense* incorporan motores matemáticos profundos que coordinan economía, asignación espacial de rutas, árboles tecnológicos y posicionamiento táctico.
* **Complejidad perceptiva equilibrada**: La resolución de entrada ($320 times 200$ o $640 times 480$) elimina el ruido de fondo visual derivado de reflejos con trazado de rayos o filtros de suavizado geométrico. Esto permite a redes convolucionales (CNN) y transformadores visuales (ViT) procesar variables críticas sin dispersar capacidad en artefactos visuales irrelevantes.
—
Implementación técnica: creación de un entorno RL sobre Play-dos
Para estructurar una canalización de aprendizaje por refuerzo eficiente, el núcleo C++ de Play-dos se encapsula dentro de una interfaz Python compatible con el estándar Farama Foundation Gymnasium.
«`
+—————————————————-+
| Flujo del Step en Gymnasium |
+—————————————————-+
|
[agent.step(action_vector)]
|
v
[Traducir action_vector a scancodes DOS vía IPC]
|
v
[Ejecutar N ciclos de CPU en el núcleo Play-dos]
|
v
+——————-+——————-+
| |
v v
[Leer Framebuffer 0xA0000] [Leer offsets destino en RAM]
| |
v v
[Ensamblar observación RGB] [Calcular recompensa y flag Done]
| |
+——————-+——————-+
|
v
Retorno: (obs, reward, terminated, info)
«`
Intercepción de las interrupciones 0x10 y 0x16: automatización de entradas y captura
El núcleo de virtualización de Play-dos sobreescribe los punteros de registro internos de DOS durante la ejecución de cada paso. Cuando un agente invoca `step(action)`:
1. El entorno decodifica el entero de acción a un evento de hardware emulado (por ejemplo, *scancodes* estándar Set 1: `0x1E` para ‘A’, `0x11` para ‘W’, `0x39` para Espacio).
2. El *scancode* se escribe en el puerto del controlador de teclado `0x60`, y se asienta una línea IRQ 1 que notifica a la CPU emulada.
3. La CPU virtual ejecuta un cupo fijo de ciclos (equivalente a un fotograma, usualmente entre $70.000$ y $100.000$ ciclos).
4. Las rutinas de introspección leen los parámetros objetivo (salud del jugador, munición, puntuación o existencias de recursos) desde direcciones fijas de RAM identificadas previamente mediante análisis binario estático.
Enlaces API en Python y envoltorios Gymnasium
A continuación se detalla una implementación funcional que ilustra la integración de Play-dos con Gymnasium:
«`python
import gymnasium as gym
from gymnasium import spaces
import numpy as np
import mmap
import os
import struct
class PlayDosEnvironment(gym.Env):
«»»
Interfaz Gymnasium para el entorno de virtualización Play-dos.
Expone memoria de video VGA Modo 13h e inyecta scancodes vía IPC POSIX.
«»»
metadata = {«render_modes»: [«rgb_array»], «render_fps»: 35}
def __init__(self, ipc_handle: str, memory_map_file: str):
super().__init__()
# VGA Modo 13h: 320×200 indexado de 8 bits transformado a RGB de 24 bits
self.observation_space = spaces.Box(
low=0, high=255, shape=(200, 320, 3), dtype=np.uint8
)
# Espacio de acciones discretas de teclado (Idle, Arriba, Abajo, Izq, Der, Acción 1, Acción 2)
self.action_space = spaces.Discrete(7)
self.action_map = {
0: 0x00, # No-op
1: 0x48, # Flecha Arriba
2: 0x50, # Flecha Abajo
3: 0x4B, # Flecha Izquierda
4: 0x4D, # Flecha Derecha
5: 0x39, # Espacio (Disparar/Interactuar)
6: 0x1D # Ctrl Izquierdo
}
# Enlace con la memoria compartida expuesta por el núcleo C++ de Play-dos
self.ipc_handle = ipc_handle
self.shm_fd = os.open(f»/dev/shm/{ipc_handle}_frame», os.O_RDWR)
self.shm_frame = mmap.mmap(self.shm_fd, 200 * 320 * 3, mmap.MAP_SHARED, mmap.PROT_READ)
self.ctrl_fd = os.open(f»/dev/shm/{ipc_handle}_ctrl», os.O_RDWR)
self.shm_ctrl = mmap.mmap(self.ctrl_fd, 64, mmap.MAP_SHARED, mmap.PROT_WRITE)
def step(self, action: int):
# 1. Traducir y escribir scancode en la memoria de control compartida
scancode = self.action_map.get(action, 0x00)
self.shm_ctrl.seek(0)
self.shm_ctrl.write(struct.pack(«=II», scancode, 1)) # Código, bandera de activación
# 2. Bloquear hasta que Play-dos ejecute ciclos y limpie la bandera
while True:
self.shm_ctrl.seek(4)
if struct.unpack(«=I», self.shm_ctrl.read(4))[0] == 0:
break
return observation, reward, terminated, truncated, info
def reset(self, seed=None, options=None):
super().reset(seed=seed)
# Indicar al hipervisor restaurar la instantánea de memoria base
self.shm_ctrl.seek(8)
self.shm_ctrl.write(struct.pack(«=I», 1)) # Disparar comando de reinicio
while True:
self.shm_ctrl.seek(8)
if struct.unpack(«=I», self.shm_ctrl.read(4))[0] == 0:
break
self.previous_score = 0
self.shm_frame.seek(0)
obs = np.frombuffer(self.shm_frame.read(200 * 320 * 3), dtype=np.uint8).reshape((200, 320, 3))
return obs, {}
def close(self):
self.shm_frame.close()
self.shm_ctrl.close()
self.shm_ram.close()
os.close(self.shm_fd)
os.close(self.ctrl_fd)
os.close(self.ram_fd)
«`
—
Modelos de visión y lenguaje (VLM) y planificación autónoma en Play-dos
La madurez de arquitecturas multimodales —como GPT-4o, Claude 3.5 Sonnet o alternativas de pesos abiertos como Qwen2-VL— permite experimentar con agentes autónomos sobre Play-dos sin depender exclusivamente de gradientes de RL. Mientras que el aprendizaje por refuerzo exige millones de pasos para deducir mecánicas elementales, los modelos VLM evalúan pantallas de juego directamente procesando sentido común espacial y semántico preentrenado.
«`
+——————————————————————-+
| Bucle de acción-percepción para agentes VLM |
+——————————————————————-+
|
[Extracción del framebuffer base (320×200)]
|
v
[Reescalado e incremento de contraste visual]
|
v
+———————————————+
| Motor de inferencia multimodal |
| (Estructuración de prompt y tokens) |
+———————————————+
|
[Plan de acción estructurado en JSON]
|
v
[Traductor a macros y temporización de scancodes]
|
v
[Inyección de hardware en Play-dos (INT 16h)]
«`
Anclaje visual e ingeniería de prompts tácticos
En juegos de estrategia clásicos como *Warcraft II: Tides of Darkness* o *SimCity 2000*, la interfaz condensa una densidad masiva de datos:
* Barras de estado con valores numéricos continuos de oro, madera, combustible, impuestos y capacidad eléctrica.
* Ventana isométrica con estructuras, accidentes orográficos y unidades dinámicas mediante *sprites*.
* Minimapas que definen el contexto macroespacial.
Para desplegar un VLM de forma fiable sobre Play-dos:
1. **Reescalado de fotogramas**: Los modelos de visión modernos procesan mejor resoluciones estándar más altas. El fotograma original ($320 times 200$) se escala mediante interpolación por vecino más cercano (*nearest-neighbor*) a $1280 times 800$, manteniendo la nitidez de pixelado sin emborronar fuentes tipográficas de baja resolución.
2. **Extracción de texto guiada**: Se instruye al modelo para que transcriba primero los elementos alfanuméricos de la interfaz antes de decidir una acción.
3. **Salida JSON estructurada**: El modelo responde exclusivamente con comandos delimitados, evitando prosa libre y fallos de análisis sintáctico.
«`json
{
«observed_state»: {
«cash_reserves»: 4520,
«rci_demand»: {«residential»: «high», «commercial»: «moderate», «industrial»: «low»},
«power_grid_alert»: true
},
«tactical_deduction»: «Zonas residenciales sin suministro eléctrico. Se requiere tender líneas de tensión desde la central de carbón principal hacia el cuadrante norte recién zonificado.»,
«action_sequence»: [
{«command»: «KEY_PRESS», «key»: «P», «duration_ms»: 100},
{«command»: «MOUSE_MOVE», «x»: 128, «y»: 84},
{«command»: «MOUSE_CLICK», «button»: «LEFT»},
{«command»: «MOUSE_DRAG», «x_end»: 145, «y_end»: 84}
]
}
«`
Bajo este esquema, Play-dos se consolida como un entorno de evaluación riguroso para medir planificación autónoma de largo alcance, tolerancia a fallos y deducción espacial a lo largo de cientos de ciclos simulados.
—
Evaluación comparativa en arquitecturas de juego de los 90
El catálogo de MS-DOS reúne diversos paradigmas computacionales que ponen a prueba diferentes facetas del modelado de inteligencia artificial:
«`
+———————————————————————+
| Panorama de evaluación en DOS |
+———————————————————————+
| |
| Motores 2.5D en primera persona Motores de simulación isométrica|
| (DOOM / Wolfenstein 3D) (SimCity 2000 / X-COM) |
| +————————–+ +————————–+ |
| | – Navegación continua | | – Micro y macroeconomía | |
| | – Reacción en tiempo real| | – Espacios de acción masivos| |
| | – Observabilidad parcial | | – Pathfinding sobre grafos| |
| +————————–+ +————————–+ |
| |
+———————————————————————+
«`
Navegación espacial en primera persona: DOOM y Wolfenstein 3D
Antes de la aceleración por hardware 3D, id Software implementó árboles de partición espacial binaria (BSP) para proyectar entornos pseudo-3D por software. DOOM dentro de Play-dos conforma un banco de pruebas óptimo para:
* **Odometría visual y estimación de profundidad**: El agente debe calcular distancias y perspectivas tridimensionales únicamente a partir de planos de proyección en 2.5D.
* **Observabilidad parcial**: Objetos y enemigos fuera del cono visual exigen el mantenimiento de mapas de memoria interna latentes.
* **Exploración de alta velocidad**: Dado que Play-dos anula el límite de refresco original del motor (los 35 FPS nativos de DOOM), algoritmos como Proximal Policy Optimization (PPO) completan millones de pasos en cuestión de minutos.
Sistemas complejos y distribución de recursos: SimCity 2000 y Civilization
Los simuladores de gestión por turnos y en tiempo real trasladan el desafío desde los reflejos directos hacia el razonamiento analítico:
* **SimCity 2000**: Presenta dependencias no lineales entre redes de agua subterránea, cableado eléctrico, tipos impositivos dinámicos, transporte público y zonificación urbana. Las arquitecturas reactivas fallan en este contexto; exigen previsión de impacto sistémico.
* **Civilization**: Enfrenta al agente a horizontes temporales de cientos de turnos. El espacio de estados incluye árboles de investigación, gestión diplomática, despliegue táctico de tropas y microgestión urbana, sirviendo como entorno de prueba ideal para arquitecturas de razonamiento estratégico.
—
Consideraciones de ingeniería: serialización de estado y memoria no volátil
Ejecutar modelos de aprendizaje profundo sobre código heredado genera particularidades a nivel de virtualización de sistemas que requieren soluciones a bajo nivel.
Volatilidad del montículo y modo protegido DPMI
Los títulos tempranos en modo real se confinan a los clásicos 640 KB de memoria base. No obstante, las producciones de mediados a finales de los 90 utilizaban extensores DOS en modo protegido (DPMI, como DOS/4GW) para acceder a direcciones lineales de 32 bits y asignar hasta 32 MB o 64 MB de memoria extendida (XMS).
«`
Memoria en modo real Modo protegido (Extensor DOS/4GW)
[0x00000000 – 0x000FFFFF] [0x00100000 – 0x03FFFFFF]
+————————-+ +————————-+
| Vectores de interr. (IVT) | | Montículo dinámico (Heap) |
| BIOS Data Area (BDA) | | Búferes de sonido/Sprites|
| RAM convencional (640K) | | Geometría de nivel/Caché |
| Video RAM VGA (A0000h) | | Ejecución en memoria alta|
+————————-+ +————————-+
«`
Al diseñar mecanismos de persistencia (*checkpoints*) para software bajo DPMI:
* El emulador no puede limitarse a capturar la memoria convencional; debe almacenar la tabla completa de descriptores lineales (GDT/LDT) junto con los segmentos de memoria alta.
* Omitir el estado de ejecución completo en modo protegido desencadena fallos de página irrecuperables (los errores clásicos `General Protection Fault` o `Interrupt 0Dh`) al restaurar el estado.
* Play-dos mantiene un registro en sombra de todos los registros extendidos de 32 bits (`EAX`, `EBX`, `ECX`, `EDX`, `ESI`, `EDI`, `ESP`, `EBP`, `CR0`, `CR3`), garantizando restauraciones deterministas al ciclo de reloj exacto.
Derivación de interrupciones de audio (IRQ Bypass)
Múltiples binarios clásicos bloquean el flujo de ejecución si la sincronización por hardware con interfaces como Sound Blaster o Gravis UltraSound no devuelve confirmaciones de estado válidas. Este problema suele manifestarse al sondear la señal de interrupción del DSP (procesador de señal digital) de Sound Blaster:
«`assembly
; Bucle característico de espera de respuesta Sound Blaster en DOS
check_dsp:
mov dx, 0x22C ; Puerto de estado del búfer de lectura DSP
in al, dx
test al, 0x80 ; Comprobar bit 7 (datos disponibles)
jz check_dsp ; Bucle bloqueante si falta el hardware de audio
mov dx, 0x22A ; Puerto de lectura de datos DSP
in al, dx
«`
Play-dos solventa estos bloqueos interceptando directamente los puertos de entrada/salida (`0x220`–`0x22F`) y respondiendo sincrónicamente con estados simulados listos (*dummy acknowledges*), permitiendo que el bucle principal de la aplicación continúe sin latencia ni dependencia de hardware de sonido físico.
¿Listo para escalar su infraestructura digital?
No permita que los cuellos de botella técnicos frenen su crecimiento. Hable sobre su proyecto en torno a Play-dos Revives 90s Gaming Gold for Modern Ai Experimentation directamente con nuestros expertos sénior en Low Cost Web Agency.




