NES Elite - Código fuente documentado de Elite para NES
(github.com/markmoxon)- Código fuente de Elite para NES de Ian Bell y David Braben, con documentación en cada línea y explicaciones en la mayoría de ellas, reconstruido manualmente a partir del desensamblado del binario original del juego
- Permite generar una imagen ROM iNES que compila un juego totalmente funcional desde el código fuente en computadoras modernas y puede cargarse en una NES real o en un emulador
- Las variantes compatibles son la variante PAL de Imagineer y la variante NTSC del sitio web personal de Ian Bell; la compilación predeterminada es la variante PAL
- La forma de explorar el código fuente es verlo en un formato legible para humanos en elite.bbcelite.com o abrir el código comentado en un IDE; el contenido del sitio web y de los archivos fuente es idéntico
- Los requisitos de compilación son BeebAsm, Python y
makeen Mac/Linux; la compilación con Python solo se ha probado en 3.x y en Windows se incluyemake.exe- En Windows se compila con
make.bat, y en Mac/Linux conmake; la salida predeterminada eselite-pal.NESen la carpeta5-compiled-rom-images - Se puede generar
elite-ntsc.NESconvariant=ntsc
- En Windows se compila con
- Las opciones de compilación controlan la selección de variante, el uso de un commander de prueba cercano al máximo, omitir la coincidencia con el binario original, desactivar la verificación crc32 y más
- Un ejemplo representativo es
make variant=ntsc commander=max match=no verify=no crc32.pycompara lado a lado los checksums y tamaños de archivo del archivo generado y del archivo de referencia extraído del código fuente original
- Un ejemplo representativo es
- Las variantes PAL y NTSC difieren en aspectos como la cantidad de ciclos del NMI handler, el encabezado Imagineer/Nintendo de la pantalla de inicio, el tiempo de espera del auto-play de la demo de combate, el algoritmo de checksum de los save slots, el número de versión interno, el mensaje oculto de copyright, el scroll text y constantes de coordenada y
- La variante NTSC no funciona en hardware NTSC real; es una emulación NTSC con el timing de NMI ajustado para el modo NTSC de algunos emuladores
- No hay archivo de licencia y se aplica la ley de copyright por defecto, por lo que solo se permite leer y hacer fork; no se permite la reproducción, distribución ni la creación de obras derivadas
1 comentarios
Opiniones de Hacker News
Hace mucho, cuando trabajaba en Frontier, David Braben me contó una anécdota interesante sobre NES Elite. Según recuerdo, al principio usaban el temporizador de hardware del NES para llevar el tiempo real y hacer que la física avanzara de forma constante aunque variara la tasa de cuadros
Durante las pruebas previas al lanzamiento de Nintendo, les dijeron que algunas unidades tempranas del NES no tenían ese temporizador funcionando correctamente y que no podían usarlo. Según me contaron, Bell/Braben hicieron entonces que cada función mantuviera su propia estimación de cuántos ciclos de reloj había usado en ese cuadro, y al final del cuadro sumaban todo para estimar el tiempo transcurrido
Pero al ver el código fuente en GitHub, parece que o lo recuerdo mal o no entendí bien lo que dijo Braben. En
elite-source-bank-7.asmhay un comentario que dice “actualiza un temporizador NMI que puede usarse en lugar del temporizador de hardware que el NES no soporta”, y parece que implementaron una especie de reloj en tiempo real contando interrupciones no enmascarablesEl die de las primeras CPU del NES tenía restos de un temporizador de intervalo programable con errores y desactivado: https://www.nesdev.org/wiki/RP2A03_Programmable_Interval_Tim...
En revisiones posteriores se eliminó por completo, y es posible que solo estuviera habilitado en cosas como kits de desarrollo. Si dependían de una función que no funcionaba en equipos de consumo, era natural que las pruebas de Nintendo lo rechazaran
Incluso si las consolas lanzadas hubieran tenido un temporizador de intervalo programable, habría servido más bien para mediciones subcuadro, como efectos raster precisos. Para medir tiempo real, el conteo de NMI tiene mucho más sentido. La NMI ocurre al inicio de cada cuadro de video, es muy constante a 60.0988 Hz, y aunque el motor del juego se ralentice y cambie la tasa de cuadros, el procesamiento del lado de la CPU no puede afectar el timing de la señal de video
Como referencia, el hardware de audio también puede generar interrupciones de temporizador, y muchos chips de expansión tienen contadores de scanlines para sincronizar el renderizado. En el NES no faltan maneras de medir el tiempo
Cuando intentaban que Nintendo aprobara algún juego, me contó que no funcionaba en una versión específica del NES estadounidense o que provocaba sobrecalentamiento del sistema. Como el calendario de lanzamiento era muy ajustado, tuvo que volar hasta la sede de Nintendo para resolverlo, y recuerdo que esa versión específica tenía una distribución de menos de 100 unidades
Más tarde encontré notas de un libro inédito, y en realidad era un poco distinto. Las pruebas de los juegos no se limitaban a la jugabilidad: había que probarlos en todas las variantes de consolas NES en las que pudieran ejecutarse. Andrew Davie, de Beam Software, recordaba que “The Three Stooges” causó problemas en un NES usado para pruebas en las oficinas de Nintendo en Washington, así que fue personalmente
Dijo que, para que el juego pasara, había “unas 23 variantes de máquina”, incluidas combinaciones de distintos fabricantes de chips. Por la falta de documentación oficial, él había hecho que los datos de sprites no se escribieran en RAM como recomendaba oficialmente, sino que se escribieran directamente cada 2 segundos, lo que hacía que el NES se calentara demasiado y provocaba parpadeo de sprites en todo el juego. Tras corregirlo, obtuvieron la aprobación para el lanzamiento, y le dijeron que esa combinación problemática de NES existía en apenas unas 5 unidades en todo Estados Unidos, así que la retiraron de la línea de pruebas de Nintendo
Hace poco empecé la secuela, Elite: Dangerous. No está exenta de problemas, pero es una experiencia bastante asombrosa
Me emocionó de una forma curiosa ver elementos de juego que vienen desde la versión de 1984. Ver cómo las naves, y en especial la estación Coriolis, pasaron de aquellos gráficos vectoriales en una pantalla mapeada en 16K, que en su momento eran de punta, a un renderizado 3D completo en 4K/60 fps me pegó emocionalmente más de lo que esperaba
Ver por fin el interior detallado de una Coriolis, con carteles, plantas y equipo de atraque, honestamente casi me sacó unas lágrimas. Aunque hoy tenga dificultades, este juego es un legado valioso y espero que siga existiendo de alguna forma
Atracar manualmente una nave espacial escuchando Blue Danube siempre era una experiencia relajante
Me pregunto por qué los simuladores y juegos espaciales siempre terminan teniendo tantos problemas. Elite Dangerous parece no ir a ninguna parte, Star Citizen se siente como una beta eterna, y KSP2 también fue decepcionante
Reflexiones que escribí hace 9 años: https://hypertexthero.com/elite-dangerous-education/
La expansión Odyssey también es divertida, y ojalá algún día agreguen caminatas espaciales extravehiculares y misiones en gravedad cero
También existe Elite - The New Kind, una versión en C casi fiel al original: https://github.com/fesh0r/newkind
Fue creada por Christian Pinder: https://www.christianpinder.com/games/
También vale la pena ver la página de Elite de Ian Bell, donde hay varias versiones originales: http://www.ianbellelite.com/
El núcleo de la versión de NES de 1991, es decir, cerca del 30% de la ROM de 128K, es esencialmente la versión de BBC Master de 1986, que a su vez es una evolución de la versión original para BBC Micro de 1984. Las versiones para Commodore 64 y Apple II también pertenecen al mismo linaje, y el desarrollo se hizo en BBC Micro
La mayor parte del código de los bancos 0, 1 y 2 provino directamente de la versión original para BBC, y también hay algo más en el banco 7. Se le añadieron nuevas rutinas de gráficos, sonido y controles al frente, pero el corazón que late sigue siendo la versión para Beeb
Ian Bell, autor de Elite, dijo que la versión de NES era su versión de Elite de 8 bits favorita
En general, dijo que su favorita era la conversión de 32 bits para Archimedes
La entrevista completa está en http://www.elitehomepage.org/archive/b5081501.htm
Interpreto que esto significa que su versión favorita es la edición en casete para BBC Micro, y que su conversión favorita es la de NES. Aunque quizá lo interpreto con optimismo porque soy fanboy de la BBC
Me gusta que al inicio de cada banco haya este shim de cambio de banco
SEI/INC $C006/JMP BEGINSe explica en detalle que lo hacen así para ahorrar espacio, pero a mis ojos la única razón por la que se necesita
JMPes por el pipeline de instrucciones, y parece que bastaría con unNOPpara vaciarloAsí que mi optimización de 2 bytes sería:
SEI/INC $FFFD ; usar el C0 dentro del vector de instrucciones en su lugar/NOPJMPes por el pipeline de instrucciones”, pero también tiene sentido para una persona. La ejecución empieza en el banco 7, así que se salta al banco 7Como nota al margen, en Game Boy el punto de entrada está en ROM0, el banco fijo, así que al menos con los MBC comunes este problema no existe desde el principio
Como punto de comparación, está el código fuente de Oolite, un clon open source de Elite escrito en Objective-C: https://github.com/OoliteProject/oolite
https://oolite.space
https://news.ycombinator.com/item?id=7894145
Jugué esto en una C64 cuando tenía 8 años. Treinta años después, sigo sin entender este código
¿Solo el banco 0 tiene 18,305 líneas de assembly? Ni idea de cómo podían mantener eso en la cabeza.
Incluso con herramientas de primer nivel, seguirle la pista al código debía requerir una organización y una disciplina enormes. Estuve investigando ensambladores de principios de los 80 para Hitachi 6303[0]/Motorola 6800[1], y es increíble lo que la gente lograba con esas limitaciones de herramientas.
Por ejemplo, los dos ensambladores de abajo solo permitían etiquetas de hasta 6 caracteres, y no tenían etiquetas locales privadas para uso dentro de subrutinas. En mi trabajo, aun limitando las etiquetas a 40 caracteres por claridad, ya se sentía así.
Dicho eso, la relativa simplicidad de estas arquitecturas resulta realmente refrescante en comparación con el trabajo embebido en sistemas modernos. Poder tener más o menos todo el estado del sistema en la cabeza sin duda es una ventaja.
0: http://www.bitsavers.org/components/hitachi/_dataBooks/U24_H...
1: http://www.bitsavers.org/components/motorola/6800/exorciser/...
En general, programar en assembly no es tan distinto de hacerlo en lenguajes de alto nivel. Organizas el código en funciones, bloques, etc. Escribir una pared larguísima de código con saltos enredados es meterse en problemas serios.
Es una pena que no sea software libre. Si yo hubiera sido el creador de Elite, habría liberado todos los ports del juego bajo una licencia libre.
De todos modos, hoy se puede jugar Oolite en una netbook barata y, gracias a su enorme lista de add-ons, obtener la misma diversión o incluso más.
Parece que el lado de Braben estaba haciendo Elite 4/Elite: Dangerous, así que no quería debilitar sus derechos de autor.
Todo código fuente debería estar documentado a este nivel