1 puntos por GN⁺ 2024-02-26 | 1 comentarios | Compartir por WhatsApp
  • Magicore Anomala implementa CG de pantalla completa y transiciones de estilo animado con las capacidades gráficas y de sonido de la Amiga lanzada en 1985, pero dentro del motor del juego hay que resolver al mismo tiempo la distribución de RAM, la división de pantalla y las limitaciones de sprites
  • En una configuración típica de Amiga 500, solo hay 512 KB de Chip RAM disponibles para gráficos y sonido, así que el tamaño sin compresión de 48 KB de una CG de 320x240 y 32 colores representa una carga importante
  • La CG se reduce a unos 8 KB con compresión ZX0, se guarda en RAM de expansión y se descomprime en Chip RAM justo antes de mostrarse, reutilizando los 48,000 bytes existentes de memoria de pantalla
  • El efecto de transición se crea haciendo que el copper cambie registros de hardware en scanlines específicas y apague y encienda el DMA de bitplanes; la CPU ajusta en cada frame los valores de la copperlist según el ancho del split
  • Las motion lines del fondo deben esquivar las dependencias de color, reutilización y bitplanes de los sprites de Amiga; los attached sprites, los bits de control falsos, mantener 1 bitplane y ajustar BPLMOD1 son los mecanismos clave

El problema de RAM al meter una CG de pantalla completa en Amiga 500

  • La plataforma objetivo de Magicore Anomala es una Amiga 500 típica, con 512 KB de Chip RAM y 512 KB de RAM de expansión
    • La memoria que el chipset de Amiga puede usar para salida gráfica y de sonido es solo la Chip RAM
    • La RAM de expansión solo puede ser accedida por la CPU, así que es difícil usarla directamente para gráficos y sonido
  • La gráfica de personaje de pantalla completa (CG) es una imagen de bitmap 320x240 con 32 colores, y ocupa 48 KB sin compresión
    • Si se consideran assets compartidos, datos de nivel y la asignación de memoria de pantalla, 48 KB es un overhead grande
  • El soporte de compresión de assets agregado recientemente usa el formato de compresión ZX0
    • La CG comprimida se reduce a unos 8 KB
    • Al cargar los assets del nivel, la CG comprimida se coloca en la RAM de expansión
    • Justo antes de mostrarse, se descomprime en Chip RAM

Una forma de no tener que conseguir 48 KB nuevos de Chip RAM

  • En lugar de buscar 48 KB vacíos adicionales de Chip RAM para la CG, se reutiliza parte de la memoria de pantalla existente
    • Imagen de fondo de la habitación
    • Capa de pantalla para renderizar objetos peligrosos
    • Área de pantalla del cuadro de texto
  • Estas tres regiones de memoria son contiguas en RAM, y su tamaño combinado es de 48,000 bytes, coincidiendo exactamente con el tamaño de la CG
  • La imagen de fondo de la habitación puede restaurarse después de que termine de mostrarse la CG, así que no hay problema en sobrescribirla
  • Descomprimir la CG toma unos 500 ms, pero se integra dentro del flujo de la cutscene para que no parezca una carga
  • El video proof-of-concept del gameplay de Magicore Anomala puede verse en YouTube

Efecto de división de pantalla y uso de copper

  • Al principio se consideró una transición vertical tipo wipe, pero para que se viera bien hacía falta un gradiente que ajustara la paleta de colores en cada scanline
    • Se concluyó que solo con el copper sería difícil configurar los 32 colores dentro de un solo blank horizontal
    • Como no se quería lidiar con “racing the beam”, se eligió un efecto de división de pantalla
  • El efecto de división de pantalla se ve más impresionante para el público general, y el copper de Amiga funciona prácticamente como si hubiera sido diseñado para este tipo de efecto
    • Un caso de un efecto similar integrado en Amiga Workbench puede verse en este video
  • En la implementación se usan juntas dos funciones de Amiga
    • El copper ejecuta su propia lista de instrucciones en paralelo con la CPU y puede cambiar registros de hardware en líneas específicas de la pantalla
    • Al configurar los punteros de pantalla en registros de hardware, se puede cambiar la memoria de pantalla a cualquier ubicación dentro de la Chip RAM

Detener el DMA de bitplanes y reanudar el dibujo después

  • Por ejemplo, si la memoria principal de pantalla empieza en 0x20000, normalmente el copper configura esa dirección en los registros de DMA de bitplanes
    • Cuando se activan los bitplanes, el DMA lee esa región de memoria en orden y la dibuja en pantalla
  • Si cada línea horizontal ocupa 0x100 bytes y se configura el puntero de pantalla en 0x20800, la pantalla parece haber hecho scroll 8 líneas hacia arriba
    • Esto se debe a que el punto de inicio de la pantalla se movió 8 líneas hacia abajo en memoria
  • La mitad superior del split se desplaza hacia arriba de esta forma
  • En el punto del split, el copper apaga el DMA de bitplanes y cambia el color de fondo a rojo
    • Los registros de hardware relacionados con bitplanes quedan en la práctica congelados en ese momento
    • Al llegar a la parte inferior del split, restaura el color de fondo y vuelve a encender el DMA de bitplanes
    • La pantalla vuelve a dibujarse desde la posición en la que se había detenido, pero la posición visible real queda más abajo
  • En cada frame, la CPU ajusta vs_TCopTop y vs_TCopBottom según el ancho actual del split
    • El ajuste del puntero de pantalla para el split superior también se hace al mismo tiempo, pero no está incluido en el ejemplo de código

Truco con sprites para las motion lines del “woosh”

  • Las motion lines del fondo animado se dibujan con sprites
    • Como los sprites se dibujan y pueden moverse independientemente de la memoria de pantalla, son adecuados para este uso
    • Aun así, los sprites de Amiga tienen muchas limitaciones y son complicados de manejar
  • Restricciones de color

    • Los sprites comparten los bitplanes y la paleta de colores, así que conviene usar la menor cantidad posible de colores
    • Las motion lines usan solo 3 colores, dejando 28 colores para la CG y 1 color para el fondo
    • En Amiga, cada par de sprites usa un rango distinto de colores de la paleta
      • Los primeros dos sprites usan los colores 16-19
      • Los siguientes dos sprites usan los colores 20-23
    • Si se hacen attach dos sprites, funcionan como un solo sprite con una paleta de 16 colores y pueden usar los colores 16-31
    • Las motion lines usan 4 attached sprites, y en los gráficos solo se usan los colores 29-31
  • Usar los mismos gráficos de sprite en varias posiciones

    • Los primeros 4 bytes de los gráficos de sprite son bits de control que especifican posición y altura
    • Esta estructura se vuelve un problema si se quiere dibujar el mismo gráfico en varias posiciones
    • Se intentó configurar directamente los bits de control del sprite con registros de hardware, pero no se logró que aparecieran en pantalla
    • El DMA de sprites de Amiga recorre los punteros de datos de sprites y dibuja en pantalla, igual que el DMA de bitplanes
    • La solución fue crear 8 sprites falsos de 4 bytes
      • Estos sprites falsos contienen solo bits de control
      • Primero, todos los punteros de sprites se configuran a los sprites falsos
      • Alrededor de la línea 19, el DMA de sprites mira los punteros y carga los bits de control
      • Después, todos los punteros se cambian a los gráficos reales de las “motion lines”
    • Como resultado, el DMA queda cargado para dibujar sprites en distintas posiciones usando el mismo gráfico, y ese cambio se maneja en la copperlist

El problema de que al apagar bitplanes también desaparecen los sprites

  • Antes de que la CG llegue a la parte superior de la pantalla, hay un espacio vacío entre la parte superior y el punto donde empieza la CG
    • Si se dejan encendidos los bitplanes en ese momento, se dibujan datos basura en pantalla
  • En esa región hay que apagar los bitplanes para evitar que el DMA lea esos datos basura
  • El problema es que si se apagan los bitplanes, los sprites tampoco se dibujan
    • Esto provoca que las motion lines solo se vean dentro del borde de la CG
  • La solución es no apagar completamente los bitplanes, sino dejar solo 1 encendido y configurar el puntero de pantalla a datos vacíos
    • Se dibuja algo en pantalla, pero el resultado visible es efectivamente nada
  • No hace falta preparar una pantalla vacía completa
    • En píxeles de 1 bit, una línea de 320 píxeles son 320 bits, es decir, 40 bytes
    • Si BPLMOD1 se configura en -40, después de cada línea el puntero regresa 40 bytes hacia atrás y vuelve a dibujar los mismos 40 bytes repetidamente
    • Basta con dejar vacíos los primeros 40 bytes dentro del safety margin de la pantalla

Resultado y detalles pendientes

  • Al principio no estaba claro si valía la pena meter este tipo de CG en el juego por la cantidad de RAM que requería, pero tras implementar la compresión de datos se confirmó que el overhead es bastante razonable
  • Esto permite añadir más adornos visuales a Magicore
  • También quedan pequeñas tareas sin cubrir
    • Por ejemplo, el problema de evitar que la parte inferior de una motion line de 100 px desaparezca de golpe después de salir por la parte superior de la pantalla
  • Este efecto no usa el blitter en absoluto
  • Amiga sigue siendo una plataforma capaz de impresionar hoy en día con su capacidad para mostrar gráficos a color, igual que impresionaba a la gente a finales de los años 80

1 comentarios

 
GN⁺ 2024-02-26
Comentarios de Hacker News
  • Entiendo exactamente qué significa “Racing the beam”. Antes, al inicio y al final de una rutina sincronizada con vsync cambiábamos el color del rayo de forma distinta para calcular cuántas líneas de escaneo de tiempo de CPU podíamos usar por frame
    Recuerdo que la dirección que se usaba para eso era $dff180. Era la paleta de color 0, así que siempre se veía también en el borde de la pantalla fuera del área del bitmap
    Ese truco también lo aprendimos todo de boca en boca, sin internet, y no sabía que todavía hubiera gente intentando exprimir más ese chipset

  • Me da mucha curiosidad saber qué tipo de personas se hacen tiempo para crear juegos en Amiga. Imagino que a la gente joven no le interesan mucho estas computadoras viejas, y quienes crecieron usándolas probablemente estén ocupados con familia y trabajo
    Incluso si no estuvieran ocupados, hay muchísimos proyectos igual de divertidos que también permiten mantenerse al día. Aun así, es realmente genial

    • Nací en 1991 y en casa teníamos una Amiga 1000 antes de pasarnos a una PC con Windows 95. Por eso siempre sentí nostalgia por la Amiga, y mi cariño creció al entender mejor esos chips únicos y potentes que le daban su rendimiento
      Ahora trabajo de tiempo completo como desarrollador indie de juegos. Hacer un juego para Amiga era casi un sueño de toda la vida, y ahora siento que tengo las habilidades para lograrlo
      Quiero mostrar que, usando herramientas actuales y el conocimiento ampliamente disponible, se puede dar nueva vida a un hardware clásico muy querido con una experiencia de juego basada en principios de diseño modernos
    • Para mucha gente, no hay nada tan divertido como Amiga, C64, Atari o ZX Spectrum
      Si conectas todo en la vida con la carrera profesional, toda tu vida termina convirtiéndose en trabajo
      Es parecido a preguntar por qué practicar pintura al óleo si existe Photoshop, o por qué restaurar un auto vintage si existe Tesla
    • Quizá no soy lo bastante joven como para entrar en ese grupo, pero me gustan mucho varias computadoras un poco anteriores a mi época. Conseguí una Commodore 64, le cambié los capacitores, reemplacé el PLA y hasta le agregué doble SID y una modificación de “cambio de región”
      La modificación de cambio de región es bastante compleja porque hay que conmutar entre dos VIC-II y dos osciladores. También tengo una MSX2; no la he usado mucho, pero tiene muchísimo encanto
      Hacerse el tiempo para escribir código de verdad para estas máquinas es difícil, pero lo veo como la mayoría de los hobbies de gente que trabaja: cuando llega la inspiración, le metes noches y fines de semana
      La retrocomputación es un hobby fascinante, gratificante y excelente. Eso sí, más que el tiempo, lo que más me molesta es el precio y la dificultad para conseguir piezas
      Da pena que en el mercado de computadoras parezca haber cada vez más gente tratando de vender caro cualquier cosa con la etiqueta “antigua” o “vintage”
      Sobre la gente de más edad no puedo hablar directamente, pero algunos de los que todavía hacen demos para Commodore 64 parecen tener un fuerte deseo de reconectar con su infancia
      Hay obras que casi cuentan esa historia de forma explícita, como la demo relativamente reciente “Mojo” de Bonzai y Pretzel Logic. Intentar hacer storytelling “serio” en una obra de demoscene puede dar un poco de cringe, pero aun así se siente entrañable
      Es un hobby que consume mucho tiempo, pero si de verdad quieres hacerte el tiempo, al final encuentras la forma
      [1]: https://csdb.dk/release/?id=232966, https://www.youtube.com/watch?v=HXi3oJ9huiI
    • Tengo un amigo que crea interfaces para conectar controles de juego nuevos a computadoras antiguas. Aquí conectó una Nintendo Balance Board para jugar Decathlon de Commodore 64
      [1] https://retro.moe/2024/02/04/bluepad32-v4-0/
      [2] https://www.youtube.com/watch?v=Nj5fZlt_834
    • Soy 5 años mayor que el autor original. Al inicio de la pandemia junté una Atari, una Amiga y algunos recursos para aprender ensamblador por diversión. También hay un curso de Udemy
      https://www.udemy.com/course/programming-games-for-the-atari...
      Pensé que al trabajar desde casa tendría más tiempo libre, pero la realidad no fue así. Aun así, algún día tengo que seguir trabajando en eso
  • Siempre me pregunté cómo se habrían visto en Amiga los juegos al estilo de las consolas japonesas, y si a la Amiga le faltaba potencia o si simplemente el diseño de la mayoría de los juegos no era de mi gusto
    Bonk fue portado de forma excelente por Factor 5, pero ellos eran prácticamente magos

  • La parte que dice “una Amiga 500 común tiene 512 KB de Chip RAM y 512 KB de RAM de expansión” es un poco imprecisa. La A500 básica solo tenía 512 KB de Chip RAM
    Muchos usuarios agregaban la expansión de RAM A501, que sumaba 512 KB de Fast RAM a los que el hardware gráfico no podía acceder directamente
    Aunque se etiquetaba como Fast RAM, por la estructura de expansión era más lenta que la Fast RAM real

    • Es la llamada Slow RAM
      La mayoría de los dueños de una A500 tenía la expansión de 512 KB en la trapdoor. Mucho software, incluidos juegos como Monkey Island, no corría sin 1 MB total de RAM
      Hoy existen ampliamente expansiones económicas para la trapdoor basadas en diseños de hardware abierto, y ofrecen 1.5 MB de Slow RAM, 512 KB de Chip RAM para llegar a 1 MB total, e incluso RTC
  • Hay algo increíblemente atractivo en programar dentro de estas restricciones

    • “El enemigo del arte es la ausencia de restricciones
  • Qué bueno ver a IE. Me alegra verlo metiéndose con la Amiga

  • Me da la impresión de que mucha gente jugó con una Amiga distinta a la que yo tuve. Sin duda había juegos que se veían geniales, pero lo mismo pasaba con la Nintendo NES, y no miro a ninguna de las dos con tanto cariño
    Aun así, mostrar cómo se hizo esta animación es muy interesante

    • Tuve ambas y, sinceramente, la Amiga se sentía como una máquina dos generaciones adelantada. Viendo la diferencia de hardware, tampoco sorprende
      La Amiga era realmente un sistema con todo incluido. Tenía una CPU avanzada de 32 bits, aceleración gráfica, audio excelente y literalmente 256 veces la RAM de la NES
      Ni siquiera la SNES se acercaba, y recién en la era de la Sega Saturn vi una máquina que superara a la Amiga
    • Solo para confirmar: ¿sabes que este es un juego nuevo que está actualmente en desarrollo?
      https://www.youtube.com/watch?v=4SB20aFHc08