Blog | Archivo | Contacto | Administración |
Hace tiempo jugué a un videojuego muy interesante llamado "Moirai". Era indie, gratuito, completable en menos de 10 minutos. Quizás su aspecto visual, de Doom venido a menos, pudiese echar para atrás a más de uno. Pero el juego brillaba de otras maneras; su atmósfera, su efecto cadena (¿experimento social?) para con los jugadores, las decisiones moralmente cuestionables. No voy a aclarar más al respecto porque odio los spoilers.
Recientemente he estado probado la beta del cliente de Steam, y ahora en mi biblioteca puedo ver todos los juegos a los que he jugado, los haya comprado o no. Y entre ellos vi el Moirai. Pero cuando fui a darle un tiento de nuevo me encontré con lo siguiente:
El juego ya no existe. Ataques a la BBDD llevaron a terminar su existencia hace algún tiempo. Y me sentí mal, me hubiese gustado jugarlo una vez más.
Así que me propuse hacerlo, aunque fuese de mala manera.
Primero busqué la versión original, por si la de Steam estuviese capada con el cartelito. Al ser ejecutada, el mensaje fue, afortunadamente, distinto:
Bien. Ahora es cuando desensamblamos, y miramos desde dónde se llaman a las funciones de libmysql: hay 3 procedimientos, para emparejar, enviar respuestas, etc.
Y también hay un par de comprobaciones con ciertas constantes, aparentemente para depurar. Una de ellas hace que en vez de usar la BBDD en el sitio del autor (la cual estaba desprotegida, y con el usuario y contraseña dentro del ejecutable sin encriptar; no me extraña que les petasen la BBDD) se use una BBDD local con parámetros por defecto (localhost / root / root).
La otra es más interesante: se salta todas las consultas y proporciona valores a huevo. Cambiando dicha constante, el juego vuelve a ser jugable sin necesidad de volver a montar una BBDD local o modificar la ruta de la de internet.
Sólo tiene un inconveniente (esta imagen no tendrá mucho sentido para quienes no lo hayan jugado):
No creo que a nadie le interese, pero por si acaso:
Supongo que más vale una victoria agridulce que una derrota amarga.
We're gonna celebrate...
Salvo alguna excepción, todos los ordenadores y consolas tienen memoria de vídeo, una zona de memoria a la que el hardware de vídeo tiene acceso (exclusivo o no) y cuya interpretación conforma la imagen en nuestras pantallas.
Una de esas excepciones es la Atari 2600: eran otros tiempos, y si no se la pusieron fue para ahorrar y poder hacer un sistema asequible. Para el programador es un infierno (y pura diversión, a partes iguales), pues toca contar ciclos, hacerte una idea de por dónde está el haz de rayos catódicos de la pantalla y cambiar en el momento justo ciertos registros hardware para ir pintando cada fila.
Otro de esos sistemas es aún más bizarro: la Vectrex.
Aquí tenemos el control de propio haz, controlando la deflexión vertical, horizontal e intensidad del mismo mediante integradores controlados por un DAC multiplexado. Básicamente, elegimos la velocidad a la que viaja el mismo, y controlamos la longitud (factor de escala normalmente fijo) en función del tiempo (un timer). Como procesador utiliza un 6809 y para el sonido un AY-3-8912, ambos viejos conocidos. Tiene un DAC que utiliza para todo, un multiplexor analógico y un 6522 para controlar los periféricos.
Al ser un proceso analógico, se comenten errores acumulativos durante el proceso de traza, siendo necesario recalibrar el haz de vez en cuando. Por comodidad visual, también es recomendable mantener una frecuencia de refresco de pantalla (50Hz por defecto) gastando ciclos al final de cada cuadro.
Como el factor de escala suele ser contante, dibujamos todas las líneas en el mismo tiempo, sean cortas o largas (depende de la velocidad). Por lo tanto, aunque no variemos el brillo / grosor, no será el mismo en longitudes distintas. Y aún más: en el inicio y final hay que activar y desactivar, habiendo unos ciclos de por medio, y haciendo que los extremos sean más brillantes.
En verdad es un sistema muy curioso, y ninguno de los vídeos que podéis ver por internet le hace justicia: sencillamente las cámaras no captan bien la imagen que ofrece por su naturaleza. Recomiendo encarecidamente ver una en persona.
Pero dejo ya de enrollarme, y vamos a grano: hace poco me han regalado una, la que veis arriba (¡muchas gracias, Jaime!). Y como viene siendo costumbre, hay que hacerle un hola mundo. Tirando de un primer emulador (no muy allá) y funciones de su propia BIOS, no se tarda mucho en lograr esto:
Bien. Pasemos al paso dos: vamos a dibujar vectorialmente mi logo. Tras vectorizar y ajustar escala a mano, hacemos un programilla que pinte del tirón. Me cambio al sistema de desarrollo Vice, bastante recomendable. ¿El resultado?
Como expliqué arriba, la Vectrex es analógica y acumula errores. Partiendo en polígonos cerrados y recalibrando entre medias, tenemos esto.
¡Bien! Aquí el proyecto pasa a la siguiente fase, probarlo en hardware real. Gracias a un cartucho flash prestado, en el cual por motivos bizarros me encuentro obligado a abrir y tener que escribir la Flash a mano, llegamos a esto.
Hmmm... Al contrario que el emulador, en el hardware real no basta con poner a 0 /BLANK y /LOW (para optimizar). Hay que vaciar el DAC y cacharrear con el multiplexor. Bueno, la solución es fácil.
Tengo que decir que esta Vectrex necesita un calibrado, quizás incluso cambio de condensadores; el laberinto del Clean Sweep no se ve muy allá tampoco.
En fin, prueba superada.
Pobre blog, la verdad es que lo tengo un tanto abandonado. A ver si poco a poco voy subiendo las cosas que he ido haciendo.
De momento, voy a empezar hablando de cuando conecté una FPGA a un PCW para sacarle vídeo en color.
La teoría es sencilla: el PCW tiene una salida de vídeo digital (vídeo y sincronismos separados, niveles TTL), enrutada hacia el conector de expansión. Por lo tanto, los píxeles son bits, y si en vez de emitirlos de uno en uno a la misma velocidad (dos colores) los emitimos de dos en dos a la mitad de velocidad (píxeles del doble de ancho; cuadrados, por tanto) tendremos cuatro colores, y si hacemos los mismo de cuatro en cuatro a una cuarta parte de la velocidad tendremos dieciséis colores.
Así que cogí mi vieja Cyclone-II y decidí conectársela al PCW para tratar la imagen de vídeo. Los pines necesarios son VIDEO y NSYNC, pero además hay que utilizar 32MHz y /RESET para derivar el reloj de píxeles y detectar el reinicio del sistema.
El primer problema que tenemos es la conversión TTL -> LVCMOS. Empecé utilizando un 74HC4050 para realizar la conversión, pero no aguanta bien las frecuencias que necesitamos.
Así que finalmente migré a un MC74LCX16245, que según su hoja de especificaciones soporta algo más de 200 MHz (¡y doy fe de ello!). Primer asunto arreglado.
Podemos pasar al plato fuerte: sacar colores en el PCW. Utilizo dos buffers del tamaño de una línea, uno para escribir la actual y otro para reproducir la anterior al mismo tiempo. Esto nos permite, además, doblar la frecuencia horizontal (volcando dos veces al doble de velocidad), con lo que además podemos sacar vídeo VGA… o HDMI.
El segundo problema: el reloj de píxeles en el PCW es de 16 MHz, el cual se deriva del de 32 MHz dentro del GA. Yo puedo hacer lo mismo en la FPGA (y lo hago); el problema es que al tener la mitad de la frecuencia haber dos posibilidades con la señal: puede estar en fase, o en oposición de fase, y no tengo forma de saber qué fase está utilizando por dentro el GA. Y en efecto, es algo que ocurría la mitad de las veces.
La solución a este inconveniente es de nuevo relativamente simple: la generación de sincronismos también va sincronizada con el reloj de 16 MHz, así que podemos deducir qué fase es la buena en determinados momentos del cuadro usando esa señal. Haciendo una máquina de estados para su sincronización en el arranque se arregla el problema, y de paso nos permite calcular los sincronismos, memoria ganada.
En una implementación, sin embargo, saco a la misma frecuencia horizontal (TV) unos dos bits por componente (seis bits, 64 colores de paleta), algo que se puede hacer fácilmente con resistencias. Para simplificar, además, uso una paleta fija en cada modo.
Como el tema funciona, le añado un modo de vídeo adicional, con atributos; al final nos queda:
Lo curioso de todo esto es que hay juegos que se ven realmente bien. Para empezar, todos los de Opera Soft tienen los gráficos portados de PC CGA, así que se ven exactamente iguales a su versión PC.
Algunos de Level 9 tienen sus gráficos portados directamente de CPC, con lo que sacan 16 colores.
Para cacharrear con todo ello, le he añadido soporte al emulador. En hardware ahora mismo tengo todo migrado a una placa con una Spartan-6 y SDRAM, bastante barata. Así puedo usar pares diferenciales TDMS y sacar vídeo (y audio) vía HDMI.
La idea es hacer una placa base que tenga buffers para todas las líneas del PCW y conectores para pinchar la placa con la FPGA y otra con un ESP32. De esa forma tendríamos WiFi, bluetooth, y conector SD además del HDMI, botones y expansión de la FPGA.
A ver si saco un rato para dedicarle a esto; de momento nadie ha considerado que esté mancillando el espíritu del PCW, así que sigo adelante.
Como conozco a ciertos lectores de este blog, empezaré citando la primera acepción según la RAE de:
preservativo, va
1. adj. Que tiene virtud o eficacia de preservar.
Bien. Aclarado ese punto, vayamos al tema. :]
El domingo pasado J. me habló de algunos juegos antiguos de PC que no estaban preservados por tener algún tipo de protección. Técnicamente lo estaban, por estar hechos los volcados en Kryoflux, pero si nadie puede usarlos para jugar en la práctica no lo están. Acepté el encargo por ser una buena causa y por los viejos tiempos peceros.
Los juegos son "Elicsir", "Juegos de relax" y "Rescate". Los tres españoles, los tres distribuidos por Proein, los tres escritos en BASIC compilado (con el Bascom de MicroSoft).
Lo primero que observo al recibir los ficheros es que Kryoflux ha sacado las imágenes como si hubiese 80 pistas a pesar de que los discos son de 40 y a pesar de habérsele indicado que dé doble paso. El arreglo es sencillo:
Una vez comprobado que las pistas extras (más allá de la 39) tampoco son necesarias también se eliminan. Se vuelcan las imágenes, se extraen los ficheros y se empieza a trabajar.
Y el primer juego no necesita más: el único problema que tenía era ese, puramente geométrico.
El segundo tiene los ficheros dentro de un directorio con caracteres ilegales. Como DosBox no tiene un DOS de verdad y su emulación deja mucho que desear no es capaz siquiera de acceder; tecleando a mano los caracteres con ALT + su código, sin embargo, sí. Viva la coherencia.
En cualquier caso, una vez extraídos los ficheros del segundo, y mezclados los de los dos discos del tercero pasamos a analizar la protección, que en ambos casos es la misma. El sistema de protección se llama aparentemente "Horus", y no está demasiado mal para la época y lugar; lo cual no quita que sea bastante facilón.
¿Cómo sé que hay protección? Simplemente mirando la entrada:
El programa desvía la interrupción $13 (acceso floppy bajo nivel), y más adelante utiliza el principio de la tabla de interrupciones para almacenar los valores que le pasa a la misma. En concreto machaca los valores de la interrupción 1 y 3, para fastidiar a los depuradores.
Analizando el código vemos que hay algo especial en la pista 17; y en efecto, si observamos esa pista:
Podemos ver bien claro esos sectores solapados. El que tiene el ID 19 es el que tiene la información necesaria. Así que lo pongo en uno legible dentro de la imagen img, y modifico el código. Con eso y saltando a mano a la rutina que decodifica y relocaliza el código (los índices para ello están presentes al final del ejecutable, sin encriptar ni nada), logramos que funcionen ambos juegos:
Finalmente, supongo que lo ideal es crear una versión del ejecutable que pueda ejecutarse sin estar dentro de una imagen de disco y sin requerir intervención. Así pues, ejecuto el código que decodifica, pero me salto el que relocaliza. Entonces, vuelco el juego a disco y, con una cabecera MZ hecha a mano, las relocalizaciones y los datos volcados monto de vuelta un ejecutable, listo para ser jugado con DosBox.
Lo triste: nada de esto sería necesario si hubiese un emulador de PC que aceptase Kryoflux, pues las imágenes contienen la protección (la cual es fácilmente replicable). El único que admite algunas protecciones es el PCE, a costa de usar un formato propio. En fin.
A posteriori, tirando de internet, he descubierto que existe una versión desprotegida del "Rescate"; básicamente han hecho lo mismo que yo, aunque se han dejado toda la basurilla de la protección en el ejecutable (por eso les ocupa más). No dará problemas con DosBox, quizás sí en algún ordenador viejuno que ande justo de RAM libre.
Para finalizar diría algo sobre las partidacas que me estoy pegando, o pondría más capturas de pantalla… pero es que son juegos realmente malos (no os dejéis engañar por los gráficos). Dejemos que las autoridades competentes se encarguen del asunto.
Hará como 3 años llegó a mi conocimiento la existencia de este dispositivo (un cacharrito muy interesante, para los servicios técnicos de la época; realiza un conjunto de pruebas muy exhaustivas para determinar posibles averías):
Su dueño, al que llamaremos R, tuvo a bien donarlo (¡muchas gracias!), para su preservación, estudio y posterior clonado, algo que ocurrió unos meses después:
El dispositivo original había estado años en un corral, con lo que estaba un tanto sucio y no funcionaba; pero estudiando el volcado de las EPROMs (afortunadamente no se había borrado la segunda por no tener tapada su ventana) pude deducir el funcionamiento de su GAL.
Pero si existió una placa de diagnósticos de 9512 (en general cualquier PCW con impresora de margarita, válido por tanto para 9512+) seguramente debió existir una de 8256, ¿no?
Pues la verdad es que sí. Hace no mucho apareció esto: http://www.computinghistory.org.uk/det/31263/Amstrad-PCW8256-Test-PCB/. Un museo, y en Inglaterra; desgraciadamente.
A veces el destino es caprichoso. Hace unos días, alguien se puso en contacto conmigo porque tenía un PCW 9512 pocho, y para poder diagnosticarlo estaba usando las ROMs que colgué en su día en la PcwWiki... junto con la placa del museo, la cual tenía en préstamo.
Esa persona, a la que llamaremos J. para que permanezca en el anonimato, amablemente me ha mandado fotos de la placa para la Wiki:
Y además ha intentado volcar el contenido de las EPROMs. Digo intentado porque, aunque su lector dice que leyeron bien, el contenido no es el correcto. La primera se cuelga directamente y la segunda no pasa su propio test de integridad.
Aquí es donde comienzo a investigar; sabemos que:
Para hacerme una idea de qué es lo que está pasando, comparo las mitades altas y bajas de dichas ROMs:
Hay diferencias, pero sólo en direcciones de la forma $xx00 (inicio de página). Tiene toda pinta de deberse al haber usado un lector USB sin alimentación externa, con lo que no lee bien los valores de los bits cuando el integrado consume más de la cuenta; los valores suelen diferir en general 1 bit, pero hay casos más graves.
Para reducir el número de casos hago lo siguiente: donde sean diferentes compruebo ese valor contra las ROMs del 9512, y en el caso de que el valor sea igual a uno de los anteriores (y en ese caso siempre lo ha sido con la segunda mitad, la situada en las direcciones más altas), lo doy por bueno. Sólo tenemos que desempatar en el resto de direcciones, las cuales son:
Tan sólo 3 en la primera ROM y 11 en la segunda. Se puede analizar caso por caso a mano.
En la primera ROM tenemos un byte que afecta a código y dos que afectan a cadenas de texto (y por tanto son fáciles de corregir); salvo el del código, cuyo valor bueno no es ninguno de los 3 (pero es fácil de deducir estudiando el programa), los otros vienen de la segunda mitad.
La segunda ROM, al tener las pruebas interactivas y por tanto tener que dibujar un teclado con disposición diferente, verificar un sistema diferente de impresión, etc. tiene más discrepancias. Pero salvo 3 valores (en verde), los otros puedo asegurar que sus valores correctos son los de la segunda mitad.
Así que, aprovechando que dicha ROM tiene que pasar un test de integridad, decido ponerle todos los bytes como la segunda mitad y hacer la prueba; ¿el resultado? Pasa dicho test, arranca y todo funciona:
La conclusión final: salvo un byte en la primera ROM, perteneciente a un segmento de código crítico, el resto de valores pueden ser perfectamente todos los de la segunda mitad de cada ROM.
Quizás me dé un venazo de los míos y haga otra tirada de placas de diagnóstico, corrigiendo algunas cosillas y soportando simultáneamente ambos conjuntos de ROMs:
Por supuesto habrá que verificar el contenido de las ROMs original antes de publicar nada en la wiki, dar créditos, etc., pero de momento ya me está sirviendo: por fin tengo los diagnósticos exclusivos de la impresora matricial, algo con cuya emulación estoy liado ahora mismo.
Y también por la información que proporciona: en estas ROMs hay un copyright, concretamente “(C) COPYRIGHT 1985 MEJ ELECTRONICS LIMITED”. Tirando un poco de la manta (o de Google, mejor dicho) descubrimos que su autor es Alastair Watkins, así como del código del controlador de la impresora, del arranque del PCW, la BIOS de los primeros PCs de Amstrad y la de la placa de diagnóstico de los mismos (la cual también tengo; pero esa es otra historia).
A veces uno empieza a hacer algo simple y al final se termina con una cadena de acontecimientos que parece no tener fin.
El detonante en este caso fue el añadirle el soporte de Dandanator a mi prácticamente abandonado emulador de Spectrum.
Costó poco, la verdad; no hay más que contar pulsos tener en cuenta timeouts y ejecutar comandos simples; toda la magia la hace el propio software que lo acompaña. Un cacharrito simple, barato, efectivo y con mucho potencial. Recomendable.
El caso es que mirando el emulador por dentro vi que había empezado a implementarle el soporte de ULA+, pero que estaba abandonado por varias razones:
Pero como ya andaba con el tema Spectrum en la cabeza decidí ponerme a ratitos con el emulador. No sólo le modifiqué el tema de vídeo, sino que además le cambié el modelado de los ciclos, contención, paginado, etc.
Y con eso quedó listo el tema ULA+ (y de rebote, emulación de efecto nieve).
Pero con el auge del ZX-UNO había que darle soporte a los modos Timex, aunque sólo fuese por el modo HAM8x1:
E incluso el modo 128x96:
Y eso nos lleva a darle soporte al DivMMC, para reproducir los vídeos a gusto. Podría haber escogido DivIDE porque la emulación IDE ya la tengo hecha por el +3e, pero he preferido usar DivMMC para usar menos puertos y no dar incompatibilidades con cierto hardware.
Por supuesto, tuve que ponerme además con mi programa editor de imágenes de disco para poder editar a gusto la tarjeta SD emulada (tenía el soporte de escritura del VFAT desmantelado). Pero eso es otra historia...
Y llegados a este punto, ¿cómo voy a dar soporte a la ULA+ y no al modo 16c ruso? Eso sería imperdonable, porque:
Así que me puse manos a la obra; modo 16c:
Y soporte de paleta a la Pentagon:
Y como siempre, algo surge: hay software que pide 512 o 1024 KB; así que hay que implementar ambos modelos de memoria. Por último, pude observar que algunos juegos y demos sonaban mal... ¡porque no estaba emulando el TurboSound! Así que, de nuevo, a emularlo; junto con la Covox, ya que nos ponemos:
Con esto el tema Pentagon se nos queda como un 1024 SL v2.666. Y de hecho, en juegos como en la versión 16c del Season of Sakura así debe seleccionarse.
Durante todo lo anterior tuve que cambiar, refactorizar, rehacer y corregir cosas a cascoporro. Si me hubiesen dicho que algún día haría esto no lo hubiese creído. En cualquier caso, fue un buen entretenimiento durante los ratos libres de la semana que duró.
Edito para decir: ¡ya funciona perfectamente! :)
Versión final: