Astéroric — funciones detalladas
Clon de estudio de Asteroids para Oric-1 48K · C + ensamblador 6502 (cc65) · licencia EUPL 1.2
Esta página recoge las funciones de Astéroric con, para cada una, qué hace y cómo. El repositorio GitHub (README, ROADMAP, CHANGELOG) sigue siendo la referencia actualizada; el manual describe el uso.
Índice
1. Renderizado vectorial HIRES
Astéroric lo dibuja todo — nave, asteroides, platillos, torpedos, letras, cifras — con segmentos, como la recreativa de pantalla vectorial, pero sobre la pantalla HIRES de mapa de bits del Oric.
Modo HIRES monocromo
240 × 200 píxeles, PAPER 0 / INK 7. El juego de caracteres se copia de $B400 a $9800 y se limpian las tres líneas de texto inferiores. El atributo de vídeo fijado al inicio es $1E (HIRES 50 Hz, PAL): con $1C (60 Hz) un RGB2HDMI no enganchaba la señal en un Oric-1 real.
Bresenham en XOR
Cada segmento se traza en XOR: volver a trazarlo lo borra, sin guardar el fondo. La rutina draw_line_xor (src/asm/line.s) es ensamblador automodificable, con una ruta dedicada a las verticales puras y tratamiento por byte en el eje horizontal. Los vértices compartidos entre segmentos se trazan una sola vez (Bresenham semiabierto); si no, el XOR los anularía.
Sprites prerrenderizados
Las formas que no giran (asteroides, platillos, cifras) se prerrenderizan y se copian en XOR en lugar de volver a trazarse segmento a segmento — es la fase 26, que llevó el tiempo de CPU libre al 39,8 %.
Antiparpadeo
Borrado y retrazado de cada entidad se agrupan en el bucle (erase → tick → draw por entidad, posiciones anteriores memorizadas) para acortar la ventana en la que un objeto falta en pantalla.
Movimiento subpíxel
Nave y asteroides en coma fija 8.8: velocidades fraccionarias y trayectorias suaves pese a la rejilla de 240 × 200. La nave gira en 32 ángulos (11,25°) con tablas precalculadas.
2. Fidelidad al arcade
La lógica de juego está transpuesta del desensamblado de la ROM arcade rev 4 (6502disassembly.com): la misma CPU que el Oric, y se conservan los nombres de variables originales por trazabilidad.
Asteroides auténticos
Cuatro formas × tres tamaños, vértices extraídos de la ROM (trabajos de Nick Mikstas), de 11 a 13 vértices por forma sin diezmado. Hasta seis asteroides simultáneos (límite de rendimiento).
Oleadas y fragmentación
Aparición progresiva de las oleadas con posiciones y velocidades tomadas del generador pseudoaleatorio del arcade; un asteroide grande alcanzado da tres fragmentos y el padre se reduce; velocidad de los fragmentos retocada (fase 29) y velocidad general reducida (fase 37) tras las pruebas.
Cilindro y toro
El paso de un borde al otro se hace por duplicación de instancia (un objeto a caballo del borde se dibuja a ambos lados); las colisiones se calculan en topología toroidal.
Nave, disparos, hiperespacio
Nave fiel al arcade de 5 segmentos (barra de cabina, muescas), llama de propulsión, torpedos de 2 × 2 px con alcance y envoltura de arcade, ráfaga con SPACE mantenida, hiperespacio con un 25 % de riesgo de morir. Vida extra cada 10 000 puntos, con tope en 60 000; como máximo cuatro iconos de vida en pantalla.
Explosiones
Destrucción de la nave en cinco restos (tablas ShipExpVelTbl/ShipExpPtrTbl de la rev 4), explosión de los asteroides en puntos efímeros con el patrón de metralla exacto del arcade.
Game over y puntuaciones
Secuencia en tres tiempos (explosión → GAME OVER → tabla HIGH SCORES), bloqueo de 5 s, cinco mejores puntuaciones conservadas en RAM durante la sesión.
3. Platillos
Grande y pequeño
Dos platillos con IA de disparo transpuesta del arcade: disparo en 8 direcciones o apuntando a la nave, precisión indexada por la puntuación, solo el pequeño por encima de 35 000 puntos.
Presión de fin de oleada
ScrSpeedup: el platillo vuelve antes cuando quedan pocos asteroides; AstBreakTimer bloquea su aparición justo después de alcanzar un asteroide.
4. Sonido AY-3-8912
El arcade original usaba osciladores analógicos discretos; los efectos de Astéroric son una recreación original en el PSG del Oric (no se reutiliza ningún dato de audio de Atari).
Reproductor bajo interrupción
El sonido lo reproduce una rutina bajo la IRQ del Timer 1 del VIA a 50 Hz (una actualización de cada dos a 25 Hz), lo que libera el bucle principal. El acceso al PSG está protegido (sei, zona temporal dedicada): se encontraron y corrigieron dos errores de corrupción bajo IRQ.
Tres canales independientes
Canal A: efectos (disparo, explosiones S/M/L, propulsión, hiperespacio, vida extra); canal B: el latido thump-thump que se acelera con el número de asteroides; canal C: el pitido continuo del platillo. Envolventes por hardware (R11-R13) para las caídas naturales.
Sintonía de título
Al entrar en la pantalla de título, «En la gruta del rey de la montaña» (Grieg, dominio público), en accelerando, legato, con doblaje de octava en el canal B.
5. Pantalla de título y presentación
Fuente vectorial A-Z
Desde la fase 40, una fuente vectorial completa (src/font.c) dibuja «ASTERORIC», «GAME OVER», «PRESS SPACE», «HIGH SCORES», «WAVE» y la pantalla CONTROLS mediante una función genérica text_draw.
Demo pasiva
Como en la recreativa, los asteroides derivan tras el título; «PRESS SPACE» parpadea; el juego espera de verdad a SPACE (sin arranque por temporizador).
HUD
Puntuación con cifras de 7 segmentos, iconos de vidas, número de oleada de dos cifras.
6. Teclado y joystick
Lectura directa del teclado
El teclado se lee por el VIA y el registro 14 del PSG, columna a columna, sin el búfer de teclado de la ROM: el juego no depende de la ROM Atmos $0265. La matriz completa de 64 posiciones (src/keys_tab.h) está documentada a partir de las tablas de la ROM y validada en hardware.
Teclas configurables
En la pantalla de título, K abre CONTROLS: LEFT, RIGHT, THRUST, FIRE, HYPER se introducen por turno, duplicados y posiciones desconocidas rechazados, ESC cancela y restaura. La asignación vive en RAM (valores por defecto al recargar).
Joystick IJK
Lectura de la interfaz IJK en el puerto de impresora (puerto A del VIA directo, strobe PB4) con bit de presencia: sin interfaz, la lectura se ignora. El primer protocolo (lectura a través del PSG) reproducía un modelo de emulador erróneo y se corrigió tras los comentarios sobre una interfaz física; Phosphoric se corrigió en paralelo. No reasignable.
7. Rendimiento
El presupuesto es de unos 40 000 ciclos por fotograma a 25 Hz en un 6502 a 1 MHz.
Planificador de paso fijo
Fase 28: paso fijo con recuperación, marcado por el Timer 1 del VIA (20 ms) — fin de los tirones de 60 ms, 25 Hz constantes. Se probó y rechazó un modo adaptativo a 50 Hz.
Mediciones
Trazado inicial a ~97 ciclos/píxel (fase 2), reducido después con la automodificación, el procesamiento por byte y los sprites prerrenderizados; tiempo de CPU libre en juego del 17,9 % al 39,8 % (fases 24-26). Perfil make bench sobre 25 millones de ciclos.
Sincronización de vídeo
La línea CB1 (VSync) no está cableada en el Oric-1 real: la cadencia viene del Timer 1 en marcha libre, no de la señal de vídeo.
8. Especificaciones
| Elemento | Valor |
|---|---|
| Máquina objetivo | Oric-1 48K, ROM BASIC 1.0 |
| Pantalla | HIRES 240 × 200 monocromo, 50 Hz (atributo $1E) |
| Cadencia | 25 Hz constantes (Timer 1 del VIA, 20 ms) |
| Sonido | AY-3-8912, 3 canales, reproductor bajo IRQ a 50 Hz |
| Entradas | Teclado (lectura VIA directa, reasignable), joystick IJK (puerto de impresora) |
| Carga | asteroric.tap (~23 KB) con indicador de autoarranque, código en $0500 |
| Lenguajes | C (cc65) + ensamblador 6502 (ca65) |
| Licencia | EUPL 1.2 (código original); elementos derivados de Atari no cubiertos |
9. Compilación y tests
Requisitos
cc65 ≥ 2.19 (cc65, ca65, ld65), Python 3 para los generadores de tablas (ship_verts.s, shapes.s) y Phosphoric para ejecutar, capturar y perfilar (ruta a ajustar en el Makefile).
Objetivos make
make produce build/asteroric.tap; make run / make run-joy lanzan en Phosphoric (teclado / IJK emulado); make test captura la pantalla sin interfaz; make check compara bit a bit con la captura de referencia versionada; make host-test compila y ejecuta los tests x86 en el host; make bench perfila 25 M de ciclos.
Tests
Tests portables en el host sobre el generador pseudoaleatorio y la tabla de teclas compartida (8 aserciones), captura de referencia de la pantalla de título comparada bit a bit, escenarios de disparo guionizados en Phosphoric (--type-keys) para la no regresión de teclado/joystick.
10. Límites conocidos
Oric Atmos
El .tap no funciona con la ROM Atmos (BASIC 1.1), ni en Phosphoric ni en Oricutron. El objetivo nominal sigue siendo el Oric-1; la compatibilidad Atmos es un sprint aparte.
Mejores puntuaciones no persistentes
Las cinco mejores puntuaciones y la asignación de teclas viven en RAM: todo se pierde al recargar. Guardado en casete/disquete en la hoja de ruta.
Seis asteroides como máximo
Límite fijado para mantener los 25 Hz; el arcade muestra más.
Torpedos
En hardware real, los torpedos siguen siendo poco visibles a alta velocidad pese al paso a 2 × 2 px.