Liber VII · Capitulum IV

El kernel

Planificar 23 escrituras en 76 ciclos y dejar el resto para el overblank.

El ARM va un ciclo por delante

Durante la imagen, el ARM solo puede adelantarse unos ciclos al 6507. Entre dos inyecciones dispone del tiempo que tarda el 6507 en ejecutar la anterior: tras una escritura, un ciclo; tras un WSYNC, el resto de la línea. Si llega tarde, el 6507 lee el último byte que vio en esa dirección, que en un kernel repetitivo a veces es la misma instrucción y «funciona por suerte». De ahí las reglas: nada de cálculos en el kernel (todo se precalcula en una caché que solo se rehace si cambian la sala, el modo o la ventana), las divisiones entre 3 son multiplicaciones y cada espera va ya calculada.

Una línea como lista de eventos

En FRANJA+ y COMPLETO cada línea es una lista de eventos: qué registro se escribe, con qué dato y en qué ciclo acaba la escritura. Cada escritura tiene una ventana válida, calculada con tiempos medidos en Stella (un RESP que acaba en el ciclo c deja el objeto en x = 3c − 63; un gráfico escrito en el ciclo c se ve desde x ≈ 3c − 68). Un planificador coloca primero las de ventana más estrecha y, si no caben, vuelve atrás. Reglas: entre dos eventos hay 0 ciclos libres o al menos 2, y el jmp cuenta como una escritura más.

No se planifica en cada línea. En FRANJA+ la tabla se resuelve una vez al arrancar y el kernel la reproduce. En COMPLETO, las parejas de líneas del damero (una A y una B, para cada campo y tipo de fila) las resuelve una herramienta fuera de la ROM, porque en el ARM costaban segundos. Una línea de COMPLETO lleva los HMOVE, tres RESP0 (uno en el ciclo 76 y dos a media línea), ocho GRP, la muestra de AUDV0 y el jmp.

Los colores de la sala, el fondo y la tinta de los jugadores, no van en cada línea: se ponen una sola vez antes de ella, sin bus stuffing, y valen para los dos campos. En el marcador solo cambian donde empieza cada tramo. Antes el campo 1 los reescribía en cada línea con bus stuffing, y en algunas teles PAL aparecían rayas de color. Solo sigue por línea el recuadro rojo de la hora.

Líneas de 76 ciclos sin WSYNC

La sala entera se emite en un solo bucle: la espera de fin de línea se suma a la del primer evento de la siguiente, y las líneas duran exactamente 76 ciclos sin WSYNC. Una línea «de cebado» apaga VBLANK con una escritura que acaba en el ciclo 76, de modo que la primera línea visible empieza ya en el ciclo 0. Eso bajó el hueco entre líneas de 93 a unas 29 instrucciones del ARM. Hoy el peor hueco del kernel está en el damero de COMPLETO: 36 instrucciones en un ciclo del 6507, unos 43 MIPS. FRANJA, FRANJA+ y DOBLE sí esperan con WSYNC entre líneas.

El algoritmo del pintor

El TIA no dibuja a Guillermo ni a los monjes: los compone el ARM en el bitmap de 128 × 160, como el original. Se ordenan los personajes de atrás adelante; antes de cada uno se pintan las baldosas aún sin pintar que no estén más cerca que él; al final, las que falten, por delante de todo. Así Guillermo pasa por detrás de columnas y arcos. El motor reproduce al píxel las 94 salas del Spectrum (reducidas) y 19 escenas con personajes.

El overblank, en cuatro tiempos

En cada overblank va como mucho una tarea pesada. Mientras alguien habla, la lógica sigue el ritmo del original: un tick cada 6 frames a 50 Hz, uno cada 7,2 a 60. Cuando nadie habla, el original corre sin esperar, y el demake también: cada tick empieza en cuanto el anterior está dibujado, uno cada 6,9 frames de media a 60 Hz, para que el personaje que sigue la cámara no avance a saltos. Ese es el ritmo nominal, el que da el interruptor de dificultad derecho en la posición que tiene al encender la consola. El Spectrum, en la práctica, no llegaba a él: andando da 6,5 ticks por segundo y no los 8,3 de su espera de 6 frames. Por eso, en la otra posición, cada tick dura un 28 % más: el ritmo lento que recuerda quien jugó al original. Al mover el interruptor, el marcador lo dice durante unos dos segundos, por encima de las frases de los monjes: «RITMO RAPIDO» o «RITMO LENTO», y en FRANJA, que tiene menos sitio, «RAPIDO» o «LENTO». Cada tick se reparte en cuatro partes: objetos, puertas y Guillermo; Adso; monjes 2 y 3; monjes 4 y 5 y el final. Una sala nueva se construye por trozos, interpretando los «programas de bloque» del original (6 bloques por overblank; una sala tiene 21 de media), y se dibuja en dos franjas. La sala nueva aparece unos 6 frames después del cambio, y mientras tanto la lógica espera, como en el original.

TareaAntesAhora (instrucciones del ARM)
Construir una sala260 000 en un overblank98 000 como máximo por overblank
Preparar las líneas (COMPLETO)85 00042 000
Sintetizar el sonido de un frame29 0009 000 – 13 000
Preparar el marcador13 0002 900 de media