Blog | Archivo | Contacto | Administración |
Los píxeles cuadrados son un lujo moderno. Los microordenadores antiguos sacaban una imagen analógica como buenamente podían, y el resultado eran píxeles no del todo cuadrados.
Empecemos por analizar la señal de vídeo PAL.
En vertical tenemos 625 filas, es decir, 312,5 por campo o 312 a secas si usamos un modo progresivo que es el caso que nos interesa, con lo que pasamos de 50 Hz a 50,08. En cualquier caso, tenemos 576 filas visibles (18,4 ms), unas 288 por campo y ese es el valor que nos interesa.
En horizontal tenemos una zona de sincronismos de 12,05 us (1,65 porche A, 4,7 sincronismo y 5,7 porche B) y una zona visible de 51,95 us. De nuevo, ese es el valor que nos interesa.
Los ordenadores de los que hablamos no aprovechan al completo la zona visible, sino que ocupan una zona activa centrada y dejan una el resto como overscan (borde) por seguridad y por simplificar hasta rellenar la visible. Esto no nos va a afectar pues vamos a analizar las frecuencias del reloj de píxeles, pero bueno es saberlo.
Sabiendo que la pantalla CRT clásica tiene una relación 4:3, entonces las cuentas son fáciles. Asumimos cada fila de igual alto con lo que tenemos 4/3*288=384 píxeles visibles en horizontal en cada una. Si ahora dividimos por el tiempo que pasamos en su zona visible (los 51,95 us) nos salen unos 7,3917… Mhz en nuestra zona visible.
Comparemos ahora algunos ordenadores y sus relojes:
Un caso interesante es el de los Spectrum 128: tienen un reloj de 2*3,5469=7,0938, con lo que tenemos un error del 4,03%. Aunque no nos influye para esto, el tiempo horizontal total son 456 px totales en vez de los 454 teóricos (228 ciclos del Z80 vs 227) que debieran ser; a cambio, sacan una fila menos (311 totales vs 312) para compensar.
Todos estos errores son relativamente pequeños, y en los emuladores se suele "arreglar" el tamaño final escogiendo la zona visible que convenga (bordes distintos a los originales para encajar en el aspecto deseado).
Mención especial a la burrada de hacer píxeles cuadrados en el modo VGA 320x200 (400 doblados vs 480 doblados nativos) que comete un error de 16,7%, claramente visible. ¿Por qué DOSBox o ScummVM no aplican el reescalado por defecto y hay que modificar la configuración? Todos los juegos se ven terribles por defecto, causando sangrado de ojos.
Y hablando de burradas, otra es ajustar el aspecto de la imagen a la del monitor en vez de mantenerlo (4:3 en 16:9 se ve un 25% más ancho, causando ya daños cerebrales).
En conclusión: aparte de haber compartido este TOC mío, si todo el mundo tuviese pantallas con muchos DPI se podría hacer un buen reescalado (y buenos efectos CRT) que mantenga el aspecto sin perder definición, pero supongo que de momento no es el caso.
Algún día tenía que llegar este momento; por fin me he decidido a portar un juego desde Spectrum al PCW, con lo que ahora debiera resultarme más fácil el volver a hacerlo.
Las diferencias entre sus arquitecturas son múltiples: diferente velocidad, sistema de contención, vídeo, matriz de teclado, mapa de memoria, frecuencia de interrupciones, altavoz en vez de zumbador, etc. Y todo eso son inconvenientes.
Pero también hay ventajas si nos lo trabajamos: partimos de pixeles cuadrados siempre (no tengo por qué buscar juegos en modo 1), modo fijo 256x192 (con lo que podemos usar siempre el modo reducido), ROM en el marco inferior (16KB de gratis para mis cosas), memoria de vídeo en posición fija (de nuevo, espacio gratis), se puede reproducir el audio por el zumbador interno del PCW (con alguna restricción), mucho monocromo gracias a los atributos (sprites o directamente la pantalla), su catálogo de exclusivos, etc.
Así que allá vamos.
Análisis:
Mirando juegos, me decido por el Movie. Ya había estudiado su versión de CPC para portarla, pero comparando con la original para localizar ciertas rutinas me decido a portar la de Spectrum como experimento.
Es una aventura isométrica interesante, con objetos, personajes, iconos de acciones y elementos conversacionales. En su día no lo tuve, pero fue uno de los primeros juegos en probar en cuanto tuve acceso a internet.
Crea en general una atmósfera bastante inmersiva. La programación es buena, la isométrica bien resuelta, el volcado de los sprites es similar a como lo hace la Abadía.
Infraestructura:
La mayor parte de mi infraestructura habitual se conserva, el mayor cambio es que utilizo mi emulador de Spectrum en vez del de CPC. Al estar mucho más pulido, puedo poner puntos de ruptura en accesos a la ULA o la memoria de vídeo, y localizar así las rutinas que necesitan parche de forma automática, medir ciclos de rutinas, veces ejecutadas, desde dónde, ...
El resto sigue siendo lo mismo, quizás mencionar que desde hace varios ports utilizo la habilidad del emulador de cargar binarios en memoria y ejecutar arbitrariamente desde línea de comandos. Con eso y mis ficheros BAT puedo probar las cosas inmediatamente sin tener que crear imágenes de disco ni cargadores.
Cargador:
No hay mucho que contar por aquí, utilizo mi cargador típico. Por cacharrear, le meto un par de efectos básicos basados en la Roller RAM con la pantalla de carga, la cual tengo comprimida dentro del propio cargador.
Frecuencia / contención:
En un Spectrum el Z80 va a unos 3,5 Mhz (3,5469 en los modelos de 128 KB), con ciclos de espera en la RAM controlada por la ULA (dos ciclos seguidos libres de cada 8, pero sólo cuando está pintando la pantalla, si no nada). La contención es por CLOCK en vez de WAIT en los modelos clásicos.
El PCW lo hace a 4 Mhz, con ciclos de espera (WAIT) en cualquier acceso a memoria (uno libre de cada cuatro); esto tiende a alinear los ciclos máquina a múltiplos de 4 ciclos de reloj.
Es difícil evaluar cuánto se pierde exactamente al desdoblar gráficos (el resto son más o menos los mismos ciclos) porque son sistemas muy distintos. No queda mal, es muy jugable, pero hago algún retoque menor para compensar.
Memoria:
Afortunadamente el PCW tiene un sistema de paginado muy potente, y nos permite comportarse casi como cualquier ordenador de la época basado en Z80. Podemos poner cualquier página de RAM en cualquier marco, así como escoger de forma separada las páginas en las que se lee y escribe en cada marco. Con esto podemos tener rutinas sobre memoria de vídeo o cosas igual de bizarras.
Originalmente tenía en escritura la VRAM del PCW y mis rutinas y teclado en lectura en la zona de la ROM ($83/$34, $80, $81, $82), pero una vez se parchearon todas las rutinas necesarias las nuevas se movieron a la zona de VRAM del ZX. De esa forma tenemos VRAM + teclado en la zona de ROM ($83, $80, $81, $82) y nos simplifica la lógica para tener código automodificable. Nos entra el juego entero + parches en 48 KB.
Acceso a ROM / FW:
Ya que la ROM del Spectrum está siempre paginada algunos juegos hacen uso de esta; y en este caso es así, aunque muy ligero.
Básicamente se usa para la lectura del teclado (escribir texto en los bocadillos y las teclas del “menú”) y cálculo de direcciones de vídeo. En ambos casos, basta con redireccionar a mis propias rutinas.
Por otro lado, hay un acceso insistente (y un tanto camuflado) al punto de entrada de la rutina de carga, entiendo que como medida de protección contra algún tipo de transfer. De nuevo, fácil arreglo.
Finalmente, se usa de nuevo en una rutina para generar aleatorios que se usan para el efecto de los pasos, por ejemplo. Al no ser aleatorios críticos (eso se hace en otra rutina), hago que mire en las 16KB superiores, donde hay más variedad de valores y el efecto es prácticamente el mismo.
Interrupciones:
Otro punto en el que se difiere; el Spectrum genera una interrupción al inicio del vídeo, mientras que el PCW tiene 6 a lo largo de cada frame PAL. Un arreglo simple sería comprobar VSYNC y si es el caso continuar el código.
Aunque en este juego no hace falta nada de esto; curiosamente, no usa las interrupciones para nada. Esto tiene sus cosas malas, como veremos cuando hablemos del teclado; por el lado positivo, tiene rutinas optimizadas que usan los registros SP e I a pelo.
Sonido:
Aunque pueda parecer que ambas máquinas son similares en este aspecto (“1b de audio”), eso no es del todo así. El Spectrum controla directamente un altavoz, mientras que el PCW tiene un zumbador (suena automáticamente a una cierta frecuencia).
Se puede encender y apagar el zumbador y el resultado es casi el mismo mientras que las frecuencias sean mayores que la del zumbador; si son menores se nos apagará y encenderá entre medias, causando una distorsión claramente audible (los que hayan escuchado la melodía del Bat-Man saben de lo que hablo).
Otro problema es que el oído detecta únicamente cambios de presión, le da igual el estado de la membrana del altavoz (encendido o apagado). Sin embargo, no puedo dejar encendido el zumbador pues seguiría sonando, algo que pasa en este juego.
Finalmente hay que aclarar que, aunque no es el caso de este juego, en un Spectrum normalmente se usa EAR para reproducir audio, pero también puede usarse MIC… ¡y ambos a la vez! Lo cual nos da una especie de 2 bits de audio, pues MIC suena más bajo que EAR.
En algunos modelos / clones esto no se lleva muy bien. Por ejemplo, en un Inves+ que los combina con XOR no hay audio en la carga, o en un Leningrad que no tiene audio por MIC se pierde la voz sintetizada del Cobra’s Arc, por ejemplo.
En cuanto a las temporizaciones, al no usar música no son críticas, así que las dejo tal cual. Si el juego hiciese uso del AY, algo que de nuevo no es el caso, hubiese sido necesario convertir las frecuencias de los osciladores (1,7735 -> 1,0 Mhz).
Vídeo:
En esta sección tampoco hay mucho que contar; uso el típico modo solapado 512x192 + fila en blanco en la página 3 para tener además el teclado, y ajuste vertical por Roller. Lo mapeo en la zona de ROM donde no estorba.
Las rutinas que acceden a la pantalla son pocas en este caso, afortunadamente. Anulo todo lo que tenga que ver con los atributos y desdoblo los gráficos al vuelo con mis rutinas. Para indicar que ocurre algo en los modos de pausa y abortar (que requieren otra pulsación para volver al juego o confirmar la salida) invierto el vídeo en el PCW.
Teclado / entradas:
Ambas matrices de teclas son completamente distintas, así que básicamente uso mis rutinas y luego tablas para convertir.
Aprovecho y le cambio las teclas raras que tiene por defecto a un clásico Q-A-O-P-Espacio, con opción de cursores. También se puede utilizar el joystick Kempston y el DkTronics.
Internamente, los controles se codifican en un byte, así que una tabla para cada caso menos el base (Kempston) y listo.
El teclado se lee en varios puntos dentro del bucle principal del juego, no por interrupciones, ya que no se usan. Esto hace que en ocasiones los controles no vayan muy finos cuando hay bastante carga de CPU. Es algo que ocurre en todas las versiones.
Fin:
Con esto llegamos al final; tenemos una versión para PCW clásico y la experiencia de portar juegos directamente desde Spectrum.
Como corolario de todo lo anterior: en este caso nos funcionan los POKEs de Spectrum en vez de los de CPC.
En algún momento tenía que dar el paso y hacer algo de software para PcW16; aprovechando las vacaciones y que tenía relativamente fresco el port del Knight Lore a PCW me pareció el momento adecuado. Es una máquina bastante más puñetera, pero bastante más potente.
Análisis:
Utilizando de nuevo como base la versión de CPC, el Knight Lore entra en 48 KB + 16 KB de memoria de vídeo, mucho más fácil para empezar que la Abadía o el Hero Quest.
Desgraciadamente, el PcW16 no tiene un modo de paginado que separe lecturas de escrituras (modo ANT), lo cual complica el parcheo: en el caso de PCW pongo en lectura una página sobre la de escritura de vídeo, dándome 16 KB extras para mis parches y tablas para acelerar, cargador, roller, etc.
Otra complicación es el teclado; al contrario que la mayoría de ordenadores de 8 bits no se leen las filas / semifilas en ciertos puertos / rangos de memoria, sino que funciona como un PC (una especie de puerto serie e interrupciones).
Por el lado positivo, el vídeo es más normal. De hecho, puedo colocarlo de la misma forma que en un CPC, con entrelazado y desperdicio de memoria incluido. Sin embargo, manteniéndolo sin entrelazar y seguido me simplifica las rutinas de volcado y me deja espacio para meter algunas de mis cosas al final.
Entorno:
Para hacer pruebas rápidas es muy cómodo usar las opciones -Y y -@ del emulador, para colocar los datos / código que quiera en la memoria y definir el mapeo y punto de entrada respectivamente. De esta forma puedo probar sin tener que hacer imágenes de disco ni crear un cargador, y puenteo completamente el sistema operativo (no hay que esperar que arranque, seleccionar la opción de ejecutar programa externo, etc.).
El resto sigue siendo similar a mi entorno de desarrollo habitual para PCW: Notepad++, Pasmo y ficheros .bat para automatizar todo. Al tener que trabajar con discos con sistema FAT añado mtools a la lista de aplicaciones.
Memoria:
Primero vamos a reservamos las 64 KB que necesitamos. No es necesario que sean contiguas, y sólo es necesario que la de vídeo esté por debajo de las primeras 256 KB. Aun así, las elijo consecutivas 4-5-6-7, y uso la 3 para el cargador, la roller (no puede estar en otro sitio en el PcW16) y los parches que no me entren en la zona principal.
Al igual que el port de PCW, la sitúo en el marco $C000-$FFFF, en el mismo sitio que la memoria de vídeo. Afortunadamente, las rutinas de vídeo parcheadas nos entran en la memoria principal en este caso, con lo que no hay problema. Al contrario que en PCW, nos toca paginar y despaginar cada vez que se llame a una de dichas rutinas, con especial cuidado de las interrupciones (que a su vez llaman a rutinas de esa área).
Video:
Lo más fácil de todo, al contrario que en PCW: en la roller podemos escoger dónde comienza cada fila de vídeo, con una granularidad de 16 bytes. Y en cada palabra de la misma tenemos además 2 bits para indicar el modo de vídeo de dicha fila.
Una curiosidad del PcW16 es que tiene los modos de video del CPC. Normalmente está en “modo 2”, pero con más del doble de filas (imagen “casi” VGA progresiva, 640x480). En este caso, usamos el modo 1 para tener 320 en horizontal con 4 colores.
Como ya he contado, la memoria va seguida y sin entrelazar. Además, las filas están dobladas (tenemos 480 en vez de 192) y con la misma vacía arriba y abajo repetida para hacer de borde en las 80 restantes.
El formato de pixeles no es el mismo que en el caso del CPC, pero es el mismo que en el caso del PCW y PCW en color, así que trabajo de conversión ahorrado.
Paleta:
Además de los modos de vídeo, también tiene el mismo sistema de paleta triestado, para un total de 27 colores distintos (aunque con diferentes valores). Sin embargo, en un PcW16 sin modear conecta sólo la componente verde al monitor monocromo, con lo cual sólo tenemos 3 tonos de gris.
No es un problema, pues en el port de PCW ya lo tuve en cuenta para el parcheo en modo mono; al fin y al cabo, un patrón %10101010 se ve igual que uno %01010101 en el monitor monocromo, pese a ser “4 pixeles de colores distintos”. Aprovechamos esa parte y es aún más sencillo, pues no hay que modificar tablas y se puede hacer directamente con la paleta, haciendo que el color 2 sea igual al 3 para que tenga más contraste en el área de juego.
Sonido:
En este caso, aprovecho la interfaz AY por el puerto paralelo para PcW16 que hice y que además tengo implementada en el emulador. A ver si saco un rato para hacer placas como Dios manda de la misma. Hereda la interfaz de joystick y DAC de la versión para PCW.
Básicamente, se usan los 8 bits de datos del puerto de forma bidireccional junto con otras 3 señales para control (lectura / escritura, datos / latch, acceso). Pero las rutinas son prácticamente las mismas.
Aprovechando que tengo que regular la velocidad del juego hago que suene el tempo de la música como en el Spectrum, un poco más despacio que en CPC (la cual me parece bastante atropellada).
Velocidad:
El PcW16 tiene un núcleo Z80 de NEC integrado en su ASIC, funcionando a unos 16 Mhz y con una contención más relajada que el CPC, lo que hace que sea aproximadamente unas 4 veces más rápido. Esto significa que el juego sin compensar es demasiado rápido.
En vez de compensar con una pausa fija en cada “fotograma” del juego, aprovechamos el sistema de compensación de velocidad por sprites no dibujados del propio juego, calibrándolo. De esta forma, logramos una velocidad casi constante independientemente de la carga gráfica. Es algo muy sencillo de implementar en este caso, pero requiere conocer el funcionamiento interno del juego.
Interrupciones:
Aquí empezamos a meternos en temas escabrosos. El PcW16 tiene en parte una arquitectura de PC; en concreto, tiene un SuperIO como los que se ponían en placas de la época. Todos sus IRQs se enrutan al ASIC, el cual genera una interrupción del Z80 en el momento que exista alguna, sea interna (video, teclado) o externa (serie 1 y 2, paralelo, disco, IDE / externo).
Afortunadamente, las externas pueden deshabilitarse (mayormente) en el SuperIO por separado, pero la existencia de la interrupción de teclado nos obliga a cambiar la lógica del gestor del juego. Además, la frecuencia de las de vídeo es de 3 por fotograma (60 Hz) en vez de 6 por fotograma (50 Hz).
Ya que comprobamos más de una cosa en el gestor, comprobamos además el botón de encendido del PcW16; si se pulsa, hacemos un warm start (además hemos conservado la página 0 de RAM), volviendo al SO.
Teclado:
Cada vez que hay al menos una tecla en el buffer del teclado, ésta se envía vía protocolo PS/2 al ASIC, dentro del cual hay un registro de desplazamiento. Cuando se recibe un byte, se genera la interrupción correspondiente y debe ser leído. Para perder la menor cantidad de tiempo, se almacena en una tabla de pulsaciones por código de tecla.
Una vez se llama a la rutina que lee las semifilas, se llama a un parche que traduce a scancodes set 2 de PC, lee las teclas correspondientes y conforma el byte. Además, si la semifila corresponde al joystick hace la lectura correspondiente del AY (a través del puerto paralelo como vimos).
Mandar de vuelta datos al teclado es un jaleo importante en el caso del PcW16, pero afortunadamente no es algo que vayamos a hacer en este juego.
Por último, y al igual que en la versión de PCW, le añado los cursores (es cómodo jugar con ellos) y el espacio como teclas de control.
Cargador:
Finalmente, con todo funcionando, hay que hacer un cargador para que el juego cargue de forma externa desde un disco. En contra de lo que alguna gente piensa, el PcW16 es capaz de ejecutar programas de forma externa.
Basta crear un fichero de hasta 16KB con extensión PRG que se carga en $4000 y ejecuta en $4100. Esos primeros bytes pueden contener lo que se quiera, pero serán machacados en memoria en el caso de la carga desde disco.
Básicamente, se reserva memoria, se cargan los datos y se muestra un diálogo para escoger monocromo o color (con el mod correspondiente, y apagando la pantalla integrada). A partir de ahí se toma el control, anula las interrupciones que genera el ratón, se pone todo en su sitio, y lanza el juego.
Fin:
Quedan cosas menores que no merece la pena casi ni mencionar, como la anulación del flag de interrupciones, saltar la inicialización de las tablas (las pongo directamente y no cambian; además, así ganamos el espacio de esa rutina para parches), las optimizaciones que hice para PCW (como la reflexión con tablas), etc.
Otra cosa que he tenido en cuenta a la hora de generar el fichero .dsk ha sido el crearle un interleave 2:1, que acelera la carga casi 10 veces. No entiendo como los discos formateados en la propia máquina no tienen esto en cuenta.
En cualquier caso, espero que disfrutéis este juego, posiblemente el primero nativo para PcW16.
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:
Hacía tiempo que quería echarle un ojo por dentro a la ROM del Spectrum Árabe. ¿Que qué es eso del Spectrum Árabe? Bueno, aquí podéis ver por ejemplo un Gris adaptado [http://k1.spdns.de/Vintage/Sinclair/86/ZX%20Spectrum%2B2%20(Arabic)/] y aquí un +2A [http://www.nightfallcrew.com/11/08/2013/restoration-and-repair-of-a-sinclair-spectrum-128k-2a-arabic-version/].
Aparentemente todas estas modificaciones se efectuaban sobre un modelo inglés al que se le dotaba de una nueva EPROM (con una nueva ROM para modo 48), un conmutador para intercambiarla (por la primera ROM, en todos los modelos) y nuevas pegatinas sobre las teclas.
¿Cuál es la legalidad exacta de estos engendros? En los mensajes de dicha ROM se menciona a Amstrad y Sinclair, así como a Matsico (o Matsiko) que supuestamente era un distribuidor oficial por aquellos lares. Y en todos los casos, el autor es un tal Dr. Nabil Nazmi y existieron al menos 3 versiones de la misma.
La ROM es una modificación de la de un Spectrum 48 KB, no tiene las rutinas de paginado ni los comandos PLAY o SPECTRUM. Tiene traducidos todos los tokens, mensajes de error, mensajes de cinta, scroll, ... y la fuente de caracteres. Tiene por tanto parcheadas las rutinas pertinentes, especialmente las de impresión en pantalla (¡va de derecha a izquierda!) y en especial las de impresión en la ZX-Printer que están rehechas.
Aprovecha la zona "sobrante" de la ROM original (rellena con $FF) para meter sus parches y algunos mensajes; eso puede crear algunas incompatibilidades con juegos que la usen como tabla para el modo de interrupciones 2.
Pero en cualquier caso, la ROM es válida para cualquier Spectrum. Una vez instalada en un modelo 128, en caso de arrancar con ella es equivalente a entrar directamente en modo 48 (pero sin activar el latch de paginación, es decir modo USR0).
Para los juegos que no usan la ROM para nada relacionado con la pantalla no hay diferencia alguna; pero para el resto el resultado puede ser... interesante.
Esta historia comienza cuando en mi trabajo se decidieron a pedir, entre otras cosas, altavoces para algunos ordenadores. Eran unos Trust Mila.
Al igual que otras cosas de este pedido, así como del posterior que hicimos a dicha distribuidora, iba "con bicho". Teniendo en cuenta la gravedad de los hechos (como una placa de vídeo sin montar (suelta por dentro del ordenador), un ordenador con un RAID en el que no reconocía un disco duro, creo que os hacéis una idea del control de calidad de dicha empresa).
Y así fue que al enchufar los altavoces el pobre E. (debo decir que con mala suerte reconocida desde que le conozco) resulta que su ordenador se apagó, para nunca más volver encenderse. Cada intento resultó en tufo a quemado con humillo ocasional. Y es que la fuente dejó pasar el pico provocado por un corto en el USB, cepillándose el control de potencia integrado.
Si alguno se pregunta qué pasó con la placa, diré que nada. Trust lamentaba lo sucedido, pero nos remitía a gestionar tanto el cambio de los altavoces como una posible compensación a través de la distribuidora que lo compramos, como es lógico. Y los de MCR (huy, al final lo dije) se desentendieron del tema, ofreciendo únicamente el cambio por los altavoces.
Viendo por otro lado como gestionaron los otros problemas (desconocimiento de lo que es un corto, sujeción con cola caliente de los conectores de alimentación de los discos duros "para que no se muevan", montaje de nuevo de la gráfica en el ordenador sobre plástico de burbujas (¿alguien sabe lo que es la estática?) "para que no se raye", sin al menos una pulserita antiestática tomada a tierra, ...) no sé si salimos perdiendo o ganando.
Pero me estoy desviando; los altavoces: ¿qué les pasaba? Aparentemente provocaron el corto sin estar siquiera encendidos, así que como al final no se iba a hacer nada con ellos en el trabajo me los traje a casa para echarles un ojo.
Internamente no son gran cosa, algo que era más que de esperar por el precio de los mismos. De hecho, salvo detalles como la soldadura (que dejaba bastante que desear en algunos puntos), no localicé nada con mala pinta como otros dispositivos que he tenido el ¿placer? de destripar.
Afortunadamente, el cable USB se puede separar de la placa gracias a un conector molex, así como el cable de audio. Pude comprobar que no había corto entre +5V y masa tanto en el cable como en la placa. Así que me decidí a alimentar la placa de forma externa.
¡Funciona! Luego el problema está en el cable; pero si no tiene corto entre los dos pines de alimentación, ¿qué puede ser? Vamos a destripar el conector USB.
¿Veis ese pegote de estaño? Como veis encaja perfectamente en forma con el trozo de goma derretido que se quedó en el lado derecho de la foto del conector.
Pues resulta que estaba tocando mecánicamente (salió solo, no estaba soldado) la línea de +5V (cable rojo)… ¡y el apantallamiento metálico externo! El cual va conectado a masa en el interior del ordenador (aunque no de algunas fuentes de alimentación autónomas para móviles, etc.; quizás por eso escapó este hecho al control de calidad de Trust). Ahí tenemos el corto, y los altavoces funcionan perfectamente al tener quitado el pegotón.
¿Hubo final feliz? Algo así; le puse un conector nuevo, y ahora dichos altavoces son los que uso para reproducir la música AY / digitalizaciones DAC del clon de DK’tronics en mi PCW.
Ya que estaba le añadí un par de condensadores (en la entrada de la fuente y sobre el integrado) para filtrar un poco el ruido de la fuente. Tengo pendiente filtrar además la entrada del audio, y mejorar el aislamiento en salida del amplificador. En cualquier caso suenan mejor y tienen mucha mejor presencia que los que usaba antes, un detalle a tener en cuenta para exposiciones.
El Orel BK-08 es un clon ruso de Spectrum relativamente compatible y con algunas mejoras. Entre ellas una interfaz de joystick dual Sinclair / Kempston integrada, una memoria sombra bajo la ROM y una segunda ROM, con la posibilidad de conmutar todo esto por software (puerto 127). Tampoco tiene memoria contendida o el bug ULA - refresco Z80. Personalmente os recomiendo pinchar una ROM estándar en el segundo banco; de esta forma tendremos una mayor compatibilidad y un teclado que funciona normalmente.
Lo bueno es que hace tiempo conseguí uno de estos cacharros relativamente raros, con la caja original todavía precintada. Lo malo es que venía con bicho.
La segunda foto es una medida de la velocidad a la que está funcionando el Z80, tirando por lo bajo (superaba los 9 a veces). Se debía a un integrado estropeado y, desgraciadamente, esa sobre frecuencia hizo sufrir al resto de la circuitería.
Pero poco a poco fui apañándole, sacando imagen sin el papel del centro y luego con cosas hasta que logré el ansiado mensaje de bienvenida.
Ya terminaré lo que le queda cuando tenga un rato; el caso y motivo del post es que, ya que había entendido como funcionaba, tenía que emularlo:
El software específico funciona; que yo sepa son el programa de diagnósticos (Tst) y el desensamblador (MZ80, se aloja en la memoria sombra y se invoca mediante NMI) que acompañan a este ordenador y también un juego llamado Sea Fight. Curiosamente se adjunta además una demo en la cinta suministrada, pero ésta no hace uso de ninguna característica especial del ordenador.
Y ya que hay tan poco para este ordenador, decidí portarme el Shadow of the Unicorn aprovechando esa memoria sombra. Se podría aprovechar también para cargar los cartuchos de la interfaz II, emular ZX80 / ZX81 / Jupiter ACE, ponerle un CP/M, etc.
En cualquier caso, aquí os lo adjunto en formato tzx para vuestro uso y disfrute (?).
Si alguien se pone a intentar emular un Z80 lo más fielmente posible, al final se encontrará emulando el registro interno MemPTR (también llamado WZ).
Es uno de esos registros internos de los procesadores para efectuar sus operaciones intermedias; el problema es que con cierta instrucción pueden leerse dos bits del mismo en dos flags indocumentados, de ahí que sea "necesaria" su implementación.
Se recomienda una lectura del tema en: [link].
Y este es mi punto de partida, ese documento y su ambigüedad en ciertas cosas. Por ejemplo:
1) En la lista aparecen Ret y RetI, pero no aparece RetN. ¿Acaso su microcodificación es tan diferente (la asignación del Iff correspondiente bien puede hacerse en paralelo, el resto es idéntico)? Resulta extraño creer que RetN no modifique MemPTR.
2) Aunque el documento habla de interrupciones no aclara si es sólo para las mascarables. Internamente las NMIs son bastante bizarras, pues hay un ciclo pseudo fetch (con lectura incorporada) antes de su tratamiento. Sin embargo un salto es un salto, e internamente sólo se pueden saltar a registros, luego debiera estar incluída. Otra cosa a verificar.
3) El documento menciona las instrucciones In A, (C) y Out (C), A. Pero hay un bloque entero de instrucciones In r, (C) y Out (C), r para r en [A, B, C, D, E, H, L, x]. El valor que he marcado con x no está documentado y correspondería como es lógico a (HL), pero dada la estructura del procesador no se puede acceder a memoria. El resultado es que en lectura no se asigna a ningún registro lo leído, y en escritura se pone en el bus externo el contenido del bus interno del procesador ($00 en NMOS, $FF en CMOS para un Z80 estándar).
Desgraciadamente, ningún programa de test mira otras instrucciones que no sean las que aparecen en esa lista (y el caso de la NMI es un tanto rebuscado, lo admito).
La lógica nos dice que debiera haber modificación de MemPTR en los 3 casos aunque las instrucciones no aparezcan en la lista. Y como veremos, es lo correcto.
Hoy que he tenido un rato he decidido despejar todas las dudas; me basta con construir un contraejemplo en cada caso, así que vayamos por partes:
Caso 1
Consideremos el siguiente programa rápido (para Spectrum):
Org $8000 Di Ld Hl, Siguiente Push Hl ;Retorno para RetN Ld A, ($FFFE) ;MemPtr=$FFFF RetN ;MemPTR = $80xx; bits 13 y 11 a 0 ;HIPÓTESIS Siguiente: Bit 0, (Hl) ;MemPtr a flags Push Af Pop Bc ;En C Ei Ld A, %00101000 And C Ld C, A Ld B, 0 Ret
Haciendo PRINT USR 32768 debiera escribirnos un valor: 40 si MemPTR no se modifica o 0 si lo hace. Como era de esperar, el resultado es 0, luego la lista tiene una errata en ese punto (debieran haber añadido RetN junto a Ret y RetI).
Caso 2
Comprobar la NMI es un tema peliagudo: tenemos que tener nuestro código en $66 (ROM por defecto en la mayoría de los ordenadores basados en Z80) y ser capaces de generar una NMI cuando queramos; a ser posible sin hardware externo.
Afortunadamente, hay un ordenador en el que eso es posible: ¡el PCW!
El controlador de disco NEC 765 genera interrupciones; normalmente no se tienen en cuenta en la arquitectura (p.ej. Spectrum +3, Amstrad CPC) pero sí en el caso del PCW. Y aún es más: pueden ser dirigidas a ningún lado (deshabilitadas), a la interrupción enmascarable y a la no enmascarable.
El programa aquí es un tanto más complicado, pues rápidamente deshabilita interrupciones, relocaliza un trozo en la dirección $66 para atender a la NMI, reprograma el Gate Array, y apaga el motor del disco (no lo hará la BIOS pues tenemos deshabilitadas las interrupciones). Al deshabilitarse la rotación del motor un momento después (y por variación de la línea /READY) tenemos nuestra bonita NMI. Simplemente la esperamos con un Halt (y las interrupciones deshabilitadas).
Al no poder imprimir fácilmente números, también hay que incorporar esas rutinas de soporte, restaurar las cosas como estaban, etc. Por todo lo anterior el programa es bastante más largo, así que por razones de longitud no lo listaré aquí.
La conclusión: se modifica MemPTR también. No lo considero una errata, si bien hubiese estado bien añadir una aclaración.
Caso 3
De nuevo un programa rapidito en Spectrum:
Org $8000 Di Ld Bc, $FFFE ;No pasa nada por escribir a ULA Ld A, (0) ;MemPtr=1 Out (C), C ;MemPtr = $FFFF HIPÓTESIS Bit 0, (Hl) ;MemPtr a flags Push Af Pop Bc ;En C Ei Ld A, %00101000 And C Ld C, A Ld B, 0 Ret
En este caso haciendo de nuevo PRINT USR 32768 obtenemos un resultado, si bien aquí es al revés: 0 indica que MemPTR no se modifica y 40 que sí lo hizo. Y así sucede, y de nuevo una errata: se debiera cambiar en esas instrucciones la "A" por "r", donde r es un registro de 8 bits. Se cumple para todos los casos (los cambios en el programa son triviales).
Moraleja: verificar siempre antes las cosas uno mismo; me toca hacer un par de cambios por haberme fiado.
Supongamos que queremos reducir el tamaño de varias imágenes. Es un problema ampliamente tratado, así que vamos a particularizar:
Por todo ello, haremos pruebas combinadas con diferentes formas de compresión y empaquetado (Run-Length, Huffman (siempre canónico), LZ77, Deflate, diccionario rotatorio) y ciertas transformaciones (Haar, tiles, subdivisión, algunos predictores). Dejamos fuera LZ78, LZW, y diccionarios varios cuando su tamaño se dispare.
Hagamos otra hipótesis:
Por ello es que nos compensa tratar los planos por separado, y comprimir cada uno con una técnica especializada para imágenes monocromas.
Así pues, podemos empezar a hacer pruebas para un fondo, es decir, imágenes transparente + negro. Además, eso nos da una cota superior: si el archivo comprimido ocupa Ancho*Alto/8 o más es obvio que hemos fracasado, pues es el tamaño que ocuparía empaquetando cada pixel en un bit (equivalente al caso trivial de Huffman con 2 valores, óptimo por tanto trabajando con bits completos).
Tras todas las pruebas mis conclusiones son:
Así que mis recomendaciones son:
Tipo fax (RLE y Huffman alternos).
Una forma muy usada es la compresión de los faxes: básicamente consisten en contar cuántos unos o ceros hay (run-length) y comprimir esas longitudes con códigos de Huffman (modificados). No es necesario indicar cuál es el valor que se repite pues al ser sólo dos se van alternando. Se usan árboles de Huffman distintos para las longitudes de cada valor.
En mi caso usaré árboles creados aposta para la imagen en vez de unos genéricos y no usaré códigos modificados pues no hay longitudes grandes al ser una imagen pequeña.
Debo decir que no funciona nada mal el algoritmo, es el segundo mejor de todas mis pruebas; como ejemplo:
Se comprime en 2987 bytes + diccionario aparte (las longitudes en bits de los códigos Huffman canónicos, para reconstruir los árboles / tablas). Los diccionarios van aparte por si se quieren unificar códigos en toda la aplicación, compartir, o lo que sea. Pongamos unos 40-60 bytes extras.
En cualquier caso, estamos hablando de unas 3K en una imagen cuyo límite estaba en 8K. Es decir, un 37,5% del original, que no está nada mal. Este algoritmo funciona de vicio en cualquier tipo de imágenes.
Subdivisión recursiva + Huffman.
Sin embargo, dadas mis restricciones de espacio necesito más compresión que el método anterior. Y dada la estética de mis imágenes haré otra hipótesis:
Cogemos una imagen, le ajustamos la exposición y gamma y empezamos a comprimir:
-> |
Tenemos el límite en 128x96/8=1546 bytes. El método anterior lo deja en 499 + diccionarios. Pongamos 550 bytes en total.
Empezamos extendiendo las dimensiones para que la imagen entre en un cuadrado cuyo lado sea potencia de 2. Ahora construimos un árbol cuaternario donde las hojas sean los cuadrados de color a dibujar. Es decir, sólo codificamos el color, y si un nodo no es hoja entonces no se dibuja (es de soporte). Por tanto, cada nodo se puede codificar con 4 bits indicando si tiene o no hijos en cualquiera de las 4 direcciones.
Se generan 1700 nodos (1025 hojas), empaquetando tal cual son 850 bytes. Pero no vamos a empaquetar sino aplicar huffman.
Nos quedan 534 bytes, todo incluido. Pero se puede hacer mejor: reordenemos el árbol, que se emita en orden de recorrido por anchura en vez de profundidad; de esta forma todas las hojas del último nivel (a 0) estarán juntas, y por tanto se pueden quitar asumiendo que a partir de que terminen los datos siempre se da ese valor (quedando 1065 de 1700 nodos).
Y así se queda en 433 bytes, incluyendo diccionario, flags y dimensiones (sólo necesita el Log2 del lado del cuadrado). En total un 28,19% del total, nada mal para una imagen no especialmente buena, y dejando abierta la posibilidad de comprimirse aún más (hay muchas rachas de 0's y 15's antes de pasar por Huffman).
¿Me dará para lo que quiero? No lo sé, pero ha sido entretenido.
Desde que me leí la documentación del ASIC del PCW16 (Anne) y pude ver que en efecto saca colores y tiene sincronismos muy cercanos al estándar VGA quise hacerme con una de estas estupendas máquinas para hacer pruebas.
Esta es la placa de un PCW16 sin modificar:
Y esta es la mía ahora:
Hay que poner el conector, rehacer los pequeños DAC del rojo y azul (el del verde viene hecho), invertir sincronismo horizontal, ... Pero merece la pena.
En el monitor plano se puede apreciar una ligera interferencia; teniendo en cuenta que para probar he pasado de construirle el filtro de frecuencias a la salida (están puenteadas), que los sincronismos no son del todo iguales a los de la VGA y que justo encima tenemos el flyback del monitor a la derecha y la fuente de alimentación a la izquierda casi que esto es algo más que normal:
El monitor plano se ve realmente BLANCO y no amarillo, cosas del flash y el TFT.
Un detalle curioso: si el PCW16 tiene un monitor externo baja mucho la señal interna y apenas se ve la pantalla, y viceversa. Por supuesto, teniendo un control por software del mismo (Out &hF8, &h2F / 3F) no hay problema alguno:
Por último una prueba de color: arranco el CP/M, un Mallard BASIC, y escribo: “ ? Chr$(27);"30" ” para cambiar a "modo 0" (16 colores); ésta es la salida (no se aprecian mucho los colores en la foto pero ahí están, rojos, verdes y azules:
Y eso es todo por hoy. Para la próxima entrega ese puerto IDE... :9
Edito: ¡nuevas fotos de regalo!
Sonda lógica. ^__^
Mis primeras placas encargadas. ^_______^
Moraleja:
Como ya he contado por otro lado, mi idea era partir de la versión original, la de CPC 6128, e intentar adaptarla a PCW haciendo la menor cantidad posible de cambios.
Teniendo en cuenta que un PCW tiene un mejor sistema de paginación de memoria, que puedo derivar el sonido a la interfaz Dk’tronics (mismo integrado) y que tengo formas de hacer que la memoria de vídeo me entre en menos de 16KBs, me surgió la pregunta: ¿y si uso el propio binario y parcheo encima?
Así pues comienzo extrayendo los datos de las pistas del disco original, dividiéndolas en páginas y reordenando los bytes (pues carga de arriba abajo, curiosamente). Hacemos un archivo para cada página y podemos continuar.
Análisis:
Aunque existe un desensamblado (Vigasoco) no me resulta útil pues no es re-ensamblable y es un tanto incompleto; así que me hago el mío propio con el IDA.
Puede verse claramente que el juego es un prototipo, no una versión pulida. Por ejemplo, la página 4 entera es un debugger (decido eliminarla y aprovecharla para mi cargador y las rutinas "externas" que sean necesarias), hay un montón de rutinas de depuración anuladas, código redundante y algunas rutinas sin optimización alguna.
Supongo que le meterían prisa al autor, o bien no le dejaron terminarlo. En cualquier caso, juega a mi favor pues eso me da más espacio para meter mis parches.
Infraestructura:
Lo primero es montarnos un entorno de desarrollo adecuado. Utilizo UltraEdit con un resaltado de sintaxis para ensamblador de Z80 para la edición, y archivos de proceso por lotes para automatizar todo.
Para ello, creo una imagen de disco cruda (.img) con los datos introducidos tal cual de forma secuencial; corto en 3 partes (inicio, datos, fin) de tal forma que con un Copy /b podemos montar todo con los datos correspondientes y su .bat correspondiente. Y otro .bat para lanzar el emulador arrancado y con el disco metido.
El código se ensambla con Pasmo, empezamos con un Org en su dirección correspondiente, un IncBin para cargar el código original y a partir de ahí tranquilamente con Org podemos poner el parche correspondiente donde queramos, comprobar espacio libre con If $>..., etc.
Cargador:
Me decido a hacer un .ems como Ópera, además de ser más estándar en un PCW. Éste agrupa las páginas 3 (vídeo, en este caso pantalla de carga) y 4 (en vez del debugger tengo mi código de carga y rutinas de acceso al disco a nivel de ficheros que serán además aprovechadas para grabar partidas).
El cargador inicializa cosas como el vídeo, mueve la pantalla de presentación a la memoria de vídeo, carga cada página en su sitio y salta al código del juego. No tiene mucho más que contar.
Memoria:
El juego utiliza normalmente la configuración 0 (0-1-2-3) y ocasionalmente el resto de las páginas en el marco 1, los modos 4-7 (0-x-2-3) lo cual nos simplifica el tema. Basta localizar los:
Ld Bc, $7FCx
Out (C), C
Y cambiarlos por una secuencia que haga lo propio y ocupe lo mismo; es decir:
Ld Bc, $8yF1
Out (C), B
Donde y=1 para x=0, y x=y para el resto.
Además habilito en el cargador el modo "original" de paginado del PCW, pues me resulta útil usarlo en las rutinas del pergamino del final.
Interrupciones:
El siguiente problema son las interrupciones; el PCW tiene varias fuentes, y deben ser reconocidas cada una por separado, a su manera; no ocurre automáticamente. Afortunadamente, las de vídeo ocurren a la misma frecuencia.
En nuestro caso tenemos anuladas las de disco (como el CPC) y se nos reduce a intercalar un In A, ($F4) en el lugar apropiado. Y de nuevo en nuestro caso, en la primera llamada desde la rutina principal (tema sonido en $1060) vemos un Di redundante y un Reti que puede ser Ret (además ya hay un Reti en la rutina principal). Ahí ganamos esos dos bytes.
Sonido:
Otra cosa sencillita; basta con cambiar la rutina en $134E por:
Out ($AA), A
Ld A, C
Out ($AB), A
Ret
Vídeo:
Lo primero es eliminar lo relacionado con la paleta; al estar centralizado, basta un Ret en $3F4C. Tenemos que usar dos píxeles por cada uno del modo 1 del CPC (misma memoria de vídeo y mismos gráficos), y los colores deben ser remapeados, pues las paletas usadas no están en orden por luminosidad:
CPC | PCW |
---|---|
0 | 1 |
1 | 3 (blanco) |
2 | 2 |
3 | 0 (negro) |
El juego utiliza 256x192, pensando quizás en ser portado a Spectrum y MSX; de nuevo, algo que nos viene muy bien.
Como seguramente sabréis, el PCW es un tanto particular con el tema vídeo. Tiene un modo fijo 720x256 (PAL, en NTSC son 200) monocromo, y eso no se puede cambiar.
Sin embargo, podemos elegir dónde se encuentra cada fila en memoria gracias a una estructura, llamada roller-ram. Y además, podemos ubicar ésta donde queramos. Sólo hay una pega, y es que cuando se recorre la memoria de vídeo para construir la imagen el puntero de la misma se incrementa en 8 y no en 1, haciendo que pixeles adyacentes no tengan direcciones adyacentes (ahora, para modos de texto o mejor dicho tiles 8x8 alineadas, es genial).
Así que la ubicamos en el espacio del cargador, y hacemos que las 192 primeras líneas apunten a direcciones de la página 3 (igual que el CPC), el resto a una línea en el propio cargador entera a 0. Al arrancar detectamos PAL / NTSC y centramos verticalmente utilizando el puerto $F6.
Para ahorrar memoria de vídeo y que nos entre en una página utilizamos el truco de solapar las líneas:
Vamos a considerar filas de caracteres (8 píxeles) por el incremento astuto del que hablamos antes. Cada una de ellas tiene por tanto el mismo ancho que su tamaño en bytes (720).
Por tanto nos sobran 720-512=208 bytes; sin embargo, no podemos poner 104 por cada lado pues no es divisible entre 16; así que los divido como 96+112 (es importante que por la derecha quede igual o más que por la izquierda, porque vamos a solapar y el lado izquierdo siguiente será el derecho anterior).
De esta forma nos ocupa todo menos de 15KB, importante pues utilizo un par de trozos por el final para meter un par de tablas para optimizar y algo más importante: al final del bloque 3, el PCW mapea el teclado.
Por supuesto, dada la no-adyacencia de la memoria de vídeo tenemos que rehacer TODAS las rutinas gráficas del juego, las que generan tablas para ser usadas por éstas y algunas de las que les pasan parámetros a las anteriores. Por cierto, yo me pregunto: ¿qué se fumaron los ingenieros de Amstrad para decidir que el CPC tuviese entrelazados los bits de los píxeles en modos empaquetados?
Teclado:
Leer el teclado en un CPC es un infierno, hay que darse garbeos por el PPI, el PSG (a través del PPI, de nuevo), etc. En el PCW sin embargo tenemos siempre su estado en una dirección de memoria, un auténtico lujo. Sólo tengo que cambiar la rutina en $32BC por una que emule el trabajo del CPC y luego cambiar las comprobaciones de códigos de teclas donde correspondan; afortunadamente son teclados bastante parecidos.
De paso, le añado los cursores además de A-Z-K-L por comodidad.
Fin:
Por supuesto quedan parches variados: me salto el poner el modo de vídeo, hago mi propia copia de las rutinas del pergamino y su recuperación al final (para que ocupen menos, como siempre que se parchea vamos pillados de espacio), se monta una tercera tabla de transparencia (sprites) y otra con las direcciones de las filas de vídeo para acelerar el juego al final del bloque 3, etc.
¿Fin?:
Escribiendo este artículo, me he dado cuenta de que... ¡no hay versión para 9512 / 9512+! Modifico el cargador para hacerlo universal, separo el sector de arranque y añado las instrucciones para generar las dos imágenes. Arreglado (y subido a la web).
Hace algún tiempo me propusieron preparar un Amstrad CPC con varios CRTCs para dárselo a cierto conocido personaje de la escena CPCera, al que llamaremos M.
Así que evalué el trabajo; piggybacking no puede hacerse más que con dos integrados (espacio) y al menos habría que ponerle tres, además de que tendría que hacerse la conmutación con el ordenador apagado y que es un tanto chapucero.
Por otro lado, podríamos tenerlos funcionando todos a la vez y multiplexar las salidas, con lo que podríamos hacer un cambio al vuelo. Sin embargo, el consumo se nos dispararía, y más sabiendo que va a tener un montón de periféricos.
Ya que ha sido entregado a su dueño, y por tanto levantado el secreto de sumario, hagamos un post lleno de fotos y meme faces sobre su elaboración.
Fase 1:
Todo empieza cuando recibo de manos de R. el CPC a modificar y varios CRTCs para ir probando, un auténtico detalle. Se pone un zócalo, se adapta un conector, se hacen algunas pruebas preliminares, y se estudia el circuito.
La idea es tener un PIC controlando todo; cuando se pulsa un botón o lo que sea, se activa la línea /RESET, se espera a que entren los buses en alta impedancia, se quita la alimentación a los CRTCs, se le pone al que queramos, esperamos que se estabilice todo y liberamos /RESET.
Nos hacemos el circuito impreso y comprobamos que la cosa funciona. Vía libre.
Fase 2:
Como siempre, aparecen complicaciones. En el conector no torneado de la placa madre no encajan bien los adaptadores de cinta plana a DIP (con lo que toca desoldar y poner uno torneado). El adaptador, por cierto, tiene la orientación invertida respecto a los conectores IDC (y requiere por tanto trenzar los cables del conector).
Pero lo peor son los tres CRTCs. Eléctricamente son bastante diferentes y se interfieren entre sí bajo ciertas condiciones.
Así que decido invertir la polaridad de la mayor parte del circuito: cortar pistas, empalmar, cambiar transistores, etc. Menudo show, pero merece la pena, sale funcionando como un campeón.
Fase 3:
Gracias a la ayuda de J. se le dan los toques finales. El conmutador de CRTCs también hace de reset, que junto con un conmutador ABBA y pausa (línea /WAIT) le dan la funcionalidad necesaria para convertirse en la máquina de demos definitiva.
O algo así.
*Pero la mano de las fotos es mía, que conste.
Supongamos que hemos hecho un emulador de PCW. Supongamos además que recientemente hemos rehecho prácticamente la emulación de Z80, corrigiendo cosas y añadiendo el escurridizo MemPTR.
¿Cómo podemos probar ese Z80? Al fin y al cabo, ZexAll no da mucho de sí, y el PCW no tiene demos (ni apenas software si me apuráis).
Solución de Habi: retroportarlo a mi viejo emulador de Spectrum, donde hay software a patadas y tenemos un montón de programas de prueba:
Por supuesto, no podía dejar de comprobar mi vieja emulación de la ULA:
¡Perfecto!
Intentaré ser poco matemático, que se me asustan los lectores.
Existe un método de construcción de fractales llamado IFS, basado en el hecho de que una aplicación contractiva tiene un punto fijo (atractor por tanto). Supongamos que trabajamos en R2 y que nuestras aplicaciones serán transformaciones afines de la forma:
Lógicamente si a, b, c y d son menores que 1 en valor absoluto, entonces es contractiva.
Generalizando: si tenemos n transformaciones así y les asociamos una probabilidad pi (con i entre 1 y n) a cada una tenemos el llamado “juego del caos”, en donde partiendo de un punto vamos transformándolo aleatoriamente según la regla que le corresponda. Y por la autosimilitud (puntos fijos) del sistema tenemos una bonita fractal. También representaremos cada aplicación en una línea para ahorrar (y para no tener que usar tensores).
Ejemplos:
- - -
Bien. Para una de las asignaturas de libre configuración de la carrera (teoría del caos) hice un programa de fractales con varios módulos, entre ellos uno IFS. Entre otras cosas. La verdad es que las prácticas fueron una sobrada en todos los sentidos; por ejemplo, incluí ésta fractal IFS con mi nombre:
El truco es fácil: dibujamos un rectángulo en un papel, y calculamos las transformaciones que lo llevan a cada uno de los palotes que conforman cada letra; además, se puede distribuir la probabilidad en función del área de cada palote, para que el relleno de puntos sea más uniforme. En los fractales anteriores el degradado de negro a color representa la densidad de puntos en esa zona.
- - - - -
Años después, cuando terminé la carrera y para celebrarlo, decidí darle una vuelta de tuerca. Una de nuestras coñas era que al unir una colección de puntos cualquiera siempre aparecía la cara de Goofy.
Así que... cogemos una imagen de Goofy (mapa de bits 256x256 representando a [0, 1]2) y por cada pixel que pertenezca a su cara escribimos la línea de la aplicación correspondiente.
Lógicamente ai=di=1/256, bi=ci=0, ei=xi/256, fi=1-yi/256, y pi=1/n para i de 1 a n (n en este caso es 10.098, el número total de píxeles y por tanto filas de la matriz) y xi e yi son la columna y fila respectivamente del pixel en cuestión en su mapa de bits correspondiente.
En cualquier caso, ésta y no otra es la historia de la fractal de la cara de Goofy.
...
[ Celebrémoslo. ]
Aquí viene otro de mis análisis, en este caso hardware: un Sprinter para PCW (una placa aceleradora para PCW, no me refiero al clon ruso de Spectrum).
Pero primero hablemos un poco del PCW: tiene un reloj de 32Mhz, el cual se divide hasta los 4Mhz para el Z80. Además, internamente tiene dos bancos de memoria dinámica, refrescada y decodificada a través del Gate Array.
Es decir, el G.A. se encarga de todo, pero a cambio nos penaliza con un único acceso cada 4 ciclos de procesador (es decir cada microsegundo, igual que el CPC). Eso nos deja una velocidad efectiva reducida de como unos 3,3 Mhz en media. Sin embargo, no hay contención por acceder al G.A. vía I/O, pero eso es otra historia.
Supongamos que ponemos un Z80 a 8Mhz con su señal de reloj correspondiente así sin más; ¿qué ocurriría?
Pues ocurriría que desde su punto de vista podemos hacer 2 accesos SEGUIDOS a memoria cada 8 ciclos. La clave está en la palabra "seguidos", por si no lo he remarcado lo suficiente: eso es algo que no ocurre en el Z80. Es decir, el Gate Array nos frenaría hasta dejarnos a la misma velocidad efectiva que teníamos originalmente.
Para que no se duerma la gente, ahí va una foto del Sprinter:
Como bien podéis ver, tenemos un Z0840008PSC (Z80 a 8Mhz, el doble que el original) por el centro, un banco de memoria en la parte superior (a base de 256K x 4) hasta 1,5MB (512KB instaladas en este caso) y en la esquina inferior derecha una bonita memoria estática de 128KB (TC551001PL).
Atención al detalle del puente usando hilo esmaltado de cobre. Los dos cables que salen (amarillo y negro) van a parar a las señales de 32Mhz (32 = 4 (frecuencia original, cogida del zócalo) * 8 (frecuencia del Sprinter)) y /MDIS (deshabilita el acceso a la RAM interna) respectivamente en el bus.
El Sprinter mapea su memoria a continuación de la instalada en el sistema (512KB en este caso, dando un total de 1MB de los 2MB máximos que admite de forma estándar), en la cual no hay contención pues está gestionada por el propio Sprinter. Sin embargo, tanto el CP/M como el TPA se encuentran en las 128KB inferiores (junto con la memoria de video y el mapeo del teclado).
Y esa es la función de la memoria estática anteriormente mencionada: una shadow RAM. Cuando se lee de las 128KB inferiores (exceptuando el teclado) se lee de esta memoria y no accede a la principal. Cuando se escribe, va a parar a ambas. Con esta chapucilla, la velocidad se ve incrementada.
Hay software mal programado en el que esto genera incompatibilidades de sincronización (por no usar las interrupciones del G.A.) e incluso totales (por los ciclos que tenemos antes de una interrupción). Pero en general, va muy bien.
Y por completitud, ahí va la cara de pistas:
* Ningún animal, Sprinter ni Espinete fue dañado durante la elaboración de este artículo. Gracias a Jaime por prestármelo. En caso de duda, consulte a su farmacéutico.
Como algunos de los que leen este blog sabrán, hay dos firmwares distintos para el Amstrad PCW: uno para los modelos con impresora matricial y otro para los de margarita (9512 y 9512+). Y que sus discos de arranque son incompatibles entre sí por usar una suma de comprobación en arranque del primer sector.
El primer firmware puede encontrarse listado, desensamblado y comentado en esta dirección. Del segundo no hay ni rastro, sólo esta conversación. Así que tenemos dos opciones: escribir un mail a alguien con quien me estoy escribiendo y que tiene TODOS los modelos de PCW y que me diga la diferencia usando el programa ahí especificado (de hecho, esa persona participa en esa conversación) o deducirlo a partir de:
Bien. Sabiendo que sólo es necesario un cambio de un byte para lograr el arranque, y sabiendo que la suma del sector de arranque pasa de ser congruente con $FF (-1) a serlo con 1 módulo 256, lo que pide el cuerpo es el cambio en la dirección $80 de memoria, de Inc A a Dec A ($3C -> $3D).
Al incrementar en 1 la suma y sabiendo que sólo nos queda un byte por modificar, sabemos que tenemos que tocar ese otro byte restando 1 módulo 256 (ese gran número, tan importante en la informática e incluso en este blog).
Por otro lado, hagamos un CRC-16 del firmware que sí tenemos; de ahí deducimos (probando) que es un CRC-16 con el polinomio del CCITT (no el de IBM) en forma MSB curiosamente. En cualquier caso ya está calibrada nuestra prueba.
Finalmente, teniendo en cuenta que el programa son sólo 256 bytes, aplicaremos fuerza bruta; sólo hay 255 candidatos a los que restar 1 y lanzar el algoritmo de CRC hasta que dé una solución. Y la da, y es única, y todo lo anterior es congruente. La solución simplemente toca una constante tonta de un retardo, nada esencial (en $2E, de $21 a $20).
Es curioso. Hubiese sido más fácil enviar ese email, pero extrañamente esto es, desde luego, más rápido. Al menos para mí.
Finalmente he decido publicar el emulador. Esto es debido a cuatro razones:
Así que ahí va el link:
Y de regalo, mini-artículo sobre la protección (?) de los juegos de Opera:
Parte 1: Formato físico
Archivos analizados: Coleccion_Opera_Vol1.dsk, dy.dsk (Goody), Sol_Negro.dsk, corsarios.DSK, Gonzalezz.dsk, ... Todos imágenes de originales, sin cracks.
En conjunto, ganamos 18.944 Bytes / Cara y ofuscamos el juego (sólo se puede leer un directorio que contiene únicamente el EMS de arranque).
Parte 2: Software
No hay mucho que contar, la verdad. El sector de arranque es estándar, busca "????????.EMS" (GOODY.EMS, p.ej.) y lo carga (primer loader). En el directorio puede verse que han utilizado el disco de arranque del CP/M como base:
Una vez cargado, salta a $0000, de ahí a $0100 (se ve que por comodidad usan archivos COM como base) y empieza el segundo loader; inicializa memoria, video, y hace la carga de la pantalla de presentación y el juego (rutina en $0193, cargando siempre sobre el banco 1); a continuación se ejecuta tal cual (salto mediante, por la paginación, hasta $F000 y de ahí a $0100 (otra vez COM)). No hay encriptación o verificación alguna, sólo carga de sectores de 1024 bytes.
Conclusión: protección realmente simple. Además, puede volcarse la memoria y hacerse un .COM del juego en cuestión completamente desprotegido.
Vamos a explicar el otro teaser, pero antes algo de historia sobre mis emuladores. ¿Por qué? Porque lo digo yo:
Es.Pectrum
Emulador de ZX Spectrum. Modelos oficiales, clones rusos, ciclos de bus, ULA exacta, contenciones, RZX, BetaDisk, disco 3”, MultiFace, Disciple, +D, GunStick, LightGun, Interface I y II, ...
PC-Cito
Empezó como un intento de emulador de XT, acabó siendo 386 + 387, con VGA (mal emulada) y las BIOS del Bochs.
PCW.es
Y finalmente, ahora sabéis por qué tenía destripado ese PCW, y la clase de experimentos que estoy haciendo. De momento arranca LocoScript y CP/M, pero no el BatMan. Vida esta. :/
Hace mucho, mucho tiempo regalé mi primer PC (del que ya he hablado) a mis sobrinas; tiempo después acabó en una casa alquilada de la cual tenía la sospecha que iba a ser abandonada en breve; así que un buen día y con la ayuda de mi sobrina M. nos pasamos y recogimos el Spectrum 48Kb, la Atari 2600 y las "tripas" de mi viejo PC. Y el tiempo me dio la razón.
La placa no tiene dimensiones estándar y además originalmente tenía un raiser para el bus ISA, con lo que sólo tiene un conector:
Algo que he decidido arreglar hoy:
Y de paso cambiarle la sulfatada batería de NiCd:
Por culpa de las EPROMS con la BIOS no se pueden enchufar hasta el fondo placas ISA de 16 bits, pero hacen bien contacto. Podría moverlas a la zona vacía donde la RAM (ya que usa bancos de 2 chips de 4b en vez de 8 de 1b), o mejor aún: poner el zócalo por debajo y enchufar las EPROMS con las patillas dobladas al revés. Pero no es necesario, es apenas 1mm.
En cualquier caso vuelvo a tener mi viejo XT perfectamente operativo. A ver si me hago con un XTIDE, y le hago una carcasita chula, aunque sea de cartón.
Corte...
...y confección.
Siempre llega un momento en la vida de todo friki en el que tiene que hacerse sus propias placas de circuito impreso. Esto es así. No sólo de breadboard vive el hombre.
Tengo un pequeño proyecto entre manos, el cual está listo a falta sólo de la placa. Así que en vez de encargarla, me he puesto a hacerla por el método del tóner y clorhídrico. Y he aprendido mucho, cagándola en cada punto.
Si veis que el papel no se despega bien, o que el tóner no se ha transferido decentemente, cambiad de tipo papel; no es necesario rellenar las caras con cobre. ¿Mi consejo? Lo mejor que he hallado es un folleto del Telepizza. Aseguraros de que no tenga restos de celulosa más que en el sitio del tóner.
Si usáis agua oxigenada normal, usad una proporción 2:1 con respecto al salfumán, y no diluyáis. No uséis menos o tardará mucho en comerse el cobre, sobreexponiéndose los extremos de la placa.
Taladrad antes de estañar, marcando primero con un clavo y martillo el lugar. Y si lo hacéis con el equivalente chinocutre de Dremel (poco torque) podéis ahorraros el soporte vertical, o en mi caso perdiendo media tarde haciendo uno de lego.
Por último, haced un buen estañado y no apliquéis con el soldador a cascoporro.
En fin, aquí unas fotos del lego:
Y ahora de las placas mutiladas, con pruebas de todo tipo:
Hace poco me volví a instalar el Vampire Bloodlines para sacar unas capturas de pantalla comparativas con respecto al Limbo of the Lost. Sólo el juego original con su parche oficial.
Y cuál no sería mi sorpresa al comprobar que me decía que mi ordenador necesitaba al menos 15MB de RAM instalada (ni siquiera libre), y que yo sólo tenía una cantidad negativa. He aquí uno de los más típicos errores: abusar del tipo int, cuando hay cosas que no deben tener signo.
Porque el compilador genera comprobaciones con signo, las cuales nos cascan a partir de los 2GB.
Busco la cadena en un las dlls, la encuentro en Bin\engine.dll. La meto en el IDA, localizo la cadena, referencia cruzada y listo:
El API capa a partir de los 4GB, para que no casquen las aplicaciones antiguas que no usan GlobalMemoryStatusEx, así que no hay peligro de perder bits; por lo tanto cambié el 7D (jge) en 200FA494 (000FA494 en el archivo) por un 73 (jae) para hacerla sin signo. Pero bien podría ponerse un EB (jmp relativo de 8 bits) y que funcione siempre. Y a jugar.
Sé que algunos de los parches no oficiales incluyen esta librería desde el Half-life 2 (mismo engine) o algo más moderno, pero no es plan. Así al menos, fueron 4 minutos divertidos, mucho más que tener que buscar un parche por internet, bajarlo, instalarlo (sacando backups previos por si acaso), etc.
...y mirando de nuevo el disco, meses más tarde, me percato de que es un Seagate de 500GB, de esos con el firmware afectado, con los mismos síntomas que otro que me ha tocado apañar hace poco. Sólo que este siempre ha estado interno y tiene 32MB de caché en vez de 8.
Pero la solución es la misma: le mutilo un poco el conector y le doblo los 4 pines para poder meter las sondas (son el puerto serie de diagnósticos), le pongo un cartón en el conector de datos (el de varios pines en DIP, no en el del motor que son sólo 3) le conecto el PicKit2, VDD 3.3V, UART Tool, forzar consola con Ctrl-Z y a escribir los comandos pertinentes para forzar la regeneración de los datos SMART y la "partición" del sistema y del usuario. Arrancar, salvar datos, corregir firmware para dejar bien el disco y arreglado.
Afortunadamente esta vez he ido a tiro hecho, y entre que estaba todo mejor y mis métodos han sido menos invasivos en este caso puede volver a utilizarse sin problema alguno el disco duro en...
...y el caso es que me dio bastante guerra. A veces se quería comunicar conmigo, a veces no. Y desde que le desmonté por primera vez la placa no hacía más que meterme un bit espurio (pulso) al principio de todas mis transmisiones. Y si el Bus Pirate tuviese un sistema UART digno, con su timeout, no tendríamos estos problemas. Al final, para reducir el ruido lo tuve un rato en el congelador y usé para comunicarme con su puerto serie el PicKit2 (que aunque también hace el UART por software, este sí funciona como Nu manda) y por fin pude arreglar esa parte.
Al final me quedé con todo; La interfaz SATA-USB es algo útil, y la fuente de alimentación la he utilizado para alimentar mi nuevo portátil.
El disco sin embargo no funciona bien sin ayudita externa, por las resistencias en las patas del controlador y los dos zeners que puse para regular el voltaje en las líneas RX y TX, pues...
...y así al entrar en mi despacho me encuentro con el portátil que me dijo que me iba a traer Jafid. Desde Marruecos, antes Alemania y antes EEUU, un flamante Epson Equity LT. Un XT de lujo (Nec V30, 10Mhz, HD de 20MB, FDD 3.5" 720KB, pantalla retroiluminada). Bastante mejor, a mi parecer, que los Amstrad PPC que había por estas latitudes.
Funciona perfectamente, aprovechando la fuente de alimentación que tenía de un disco duro externo que había petado. Después de hacerle los test rutinarios, cambiarle la disquetera y llevarme un susto con la fuente de alimentación integrada, aquí lo tengo con su DOS, su A86 y Turbo Pascal (por los viejos tiempos) y unos juegos para dejarme los ojos en esta pantalla azul y gris que se refresca como una vez cada dos segundos.
Para estos retro-ordenadores me he hecho un sistema cliente que lee o escribe sectores a través del puerto serie, y un driver para mi programa lector de imágenes; así puedo generar imágenes remotas de disco, escribir imágenes de disco in situ o bien...
...y tras comprobar que la disquetera chocheaba un poco, procedí a cambiarla por otra. Le puse una de 1.44MB que se alimenta con sólo 5V (requisito imprescindible en este portátil) y tras cambiarle el cable del disco por uno estándar recortado ya pude arrancar el DOS.
Lo malo fue al cerrarlo; al poner un tornillo en una esquina oí un débil "clack" y supe que la había cagado. Tras volver a desmontarlo entero, vi la gañanada: el tornillo era largo y justo al otro lado estaban las patas del MOSFET de potencia principal de la fuente de alimentación; así que a tomar por saco el terminal de dren (central). Un TO220 plástico de color verde en el que sólo se ve una T (Toshiba), un J147, y un superfluo *9K.
No os molestéis en buscar, pues no os aparecerá nada. Tras perder casi una hora buscando y dos chapuceando (sí, eché un pegote de soldadura, y aunque funcionó daba un voltaje ligeramente menor y se encendía todo el rato la luz de batería baja; luego puenteé fuente y dren y aunque funcionaba todo perfectamente no es ese el objetivo, pues pienso ponerle baterías nuevas), pensé: es un transistor MOSFET de canal P, vamos a buscar en la serie 2S, es decir, 2SJ147. Bingo, aunque datasheet en japonés. Hasta Toshiba te recomienda usar en su lugar un 2SJ304, con mayor corriente y algo menor resistencia, aunque al final usé otro que tenía por casa, concretamente...
A punto casi ya de cumplirse el año de permanencia que tengo con Ya.com y de mudarme a pastos más verdes me he puesto a revisar el router que me dieron en su día. Un tal SMC7908A-ISP (delegado en Arcadyan, otra del grupo Accton).
El firmware está capado y aparte es pésimo. La interfaz es lenta y mala, no hay opciones para casi nada, y tiene graves errores; como enviar peticiones DHCP en capa ATM estando la línea ADSL no sincronizada, y desincronizarla si en 4 segundos no ha obtenido su IP, ambas cosas de forma asíncrona, con lo que puede estar días sin coger línea (sin ayuda externa).
Sin embargo, el hardware es estupendo: un Infineon Danube (MIPS doble núcleo a 333 Mhz, temas analógicos para ADSL, VoIP, etc.), 64MB de RAM, 4 de Flash, un Realtek RTL8306SD para Ethernet y MII y su Atheros AR2417 para WiFi. Y un conector MiniPCI sin soldar, pero presente. Si queréis fotos, las tenéis estupendas aquí.
Dentro de su interfaz podemos abrir páginas no accesibles pero que no se han molestado en eliminar. Y es a partir de este hecho que hoy he decidido echar un ojo.
Partiendo del último firmware (v0.10.016 - 2009/07/29), extrayendo las 6 partes de las que se compone, desencriptando las 1 y 2 (núcleo firmware e interfaz web respectivamente) y descomprimiendo 1-4, nos encontramos en el caso de la 2 un bonito sistema de archivos PFS relativamente normal en routers. Una vez extraídos todos los ficheros, aquí tenéis la lista de los accesibles como interfaz web para los que queráis experimentar (\www\doc\):
accesscontroladd.stm adsl.stm adslst.stm adsl_main.stm adsl_para.stm adsl_status.stm advanced_user.stm advanced_user_p.stm arcor_network.stm arcor_spec.stm atmint_ya.stm atmpvc_ya.stm auto_upg.stm auto_upg2.stm blocked.htm changelanguage.htm clone.stm country_css.css ddns.stm ddns_main.stm dns_proxy.stm err_gen.stm firewall.stm firewallst.stm firewalltemp.stm firewall_a.stm firewall_d.stm firewall_mac.stm firewall_main.stm firewall_rule.stm firewall_rule_a.stm firewall_spi_h.stm firewall_u.stm forward_check.stm function.stm help.stm hwoption.stm igd.xml igd_l3f.xml igd_osf.xml igd_wcic.xml igd_wec.xml igd_wic.xml igd_wpc.xml index.stm ipsec_editsp.stm iptv_main.stm isp.stm js_tree.js l2tp_a.stm lan.stm lan_main.stm linegraph.class login.stm loginerr.stm loginpserr.stm menu-hid.stm menu.css menu.stm msg.js my_function.txt
|
my_function3.css nat.stmnatst.stm nattemp.stm nat_m.stm nat_main.stm nat_off.stm nat_sp.stm nat_table.stm nat_v.stm no_link.txt pingtest.stm pin_code.stm pppoeint.stm pptp_a.stm production.stm qos.stm qos_clsmap.stm qos_editcls.stm qos_main.stm qos_stats.stm qstatus_main.stm qwireless_id.stm route.stm route_main.stm route_tbl.stm routine2.txt routine_data.js r_mort.stm r_rip.stm save_ok.htm setupa.stm setupa_brief.stm setupa_main.stm setupa_top.stm setupq6_main.stm setupw.stm setupw_0.stm setupw_1.stm setupw_2.stm setupw_2_ya.stm setupw_main0.stm setupw_main1.stm setupw_main2_ya.stm setupw_menu.stm setupw_top.stm setup_dns.stm setup_q6.stm snmp.stm snmpst.stm snmptemp.stm snmp_community.stm snmp_main.stm snmp_trap.stm status.stm status_main.stm system.stm system_c.stm system_f.stm system_i.stm system_main.stm system_p.stm
|
system_r.stm system_remote_mgmt.stm system_t.stm telephony_voip.stm tl.stmtl_main.stm tools_backup.stm tools_restore.stm tr69.stm tree.js undoc_upgrade.stm upnp.stm upnp_main.stm usb_fsrv.stm usb_fsrv_part_f.stm usb_fsrv_tree.stm usb_ftp_f.stm usb_ftp_server.stm usb_ftp_tree.stm usb_main.stm usb_modem.stm usb_pr_server.stm usb_wftp_browse.stm usb_wftp_server.stm usb_wftp_tree.stm user_define.stm verinfo.txt voice_quality_test.stm voip.stm voip_account_edit_ya.stm voip_account_ya.stm voip_advanced.stm voip_call_allocation.stm voip_extension_in.stm voip_extension_out.stm voip_function.txt voip_isdn_msn.stm voip_main.stm voip_numbers_act.stm voip_num_plan.stm voip_num_plan_nr.stm voip_phone.stm voip_status.stm vpn.stm vpn_conn.stm vpn_function.txt vpn_main.stm v_lan.stm v_lan_a.stm wait.stm wait0.stm wan.stm wan_main.stm wireless.stm wirelessst.stm wirelesstemp.stm wireless_1x.stm wireless_country.stm wireless_e.stm wireless_id.stm wireless_mac.stm wireless_main.stm wireless_wds.stm |
Particularmente, me parecen útiles:
advanced_user.stm -> para hacer login como administrador, necesario para ciertas funciones; una de las pocas conocidas por ahí fuera.
wireless_country.stm -> se le pueden poner los parámetros de Japón, por ejemplo, y ganar dos bandas WiFi extras. OJO: supuestamente no es legal en Europa, hay leyes de radiofrecuencia, etc.
r_mort.stm -> nos muestra la tabla de reglas de enrutamiento vigentes (por fin).
atmint_ya.stm -> con esto podemos poner el tipo de conexión que queramos, y mandar a tomar por saco las que vienen predefinidas.
route_tbl.stm -> podemos definir nuestras reglas de enrutamiento. Con esto ya puedo tener WiFi y VoIP enrutadas al viejo router de Telefónica configurado para acceder como MER y conectarme a través suya.
También hay cosas que sobran, como lo de Arcor (el Ya.com de Alemania; incluyendo pin_code.stm) y cosas que no deberían estar realmente (como production.stm (valores de fábrica)).
La parte realmente inesperada ha sido en la carpeta de imágenes; entre otras cosas hay logos: de SMC, de Ya.com y de... ¡Pirelli! ¿Tendrá Pirelli routers como éstos personalizados? Prefiero no saberlo. Por otro lado, el firmware ha sido compilado en C bajo un entorno Unix. Nada que no me esperase.
Y con esto me conformo de momento. En cuanto me cambie de compañía y me den mi nuevo router pasaré a la fase 2: bus pirate sobre J2 (tiene un puerto serie a 3.3V) y trastear mandando mis firmwares a RAM. En teoría se podría usar OpenWrt, ya os contaré.
Llevaba mucho tiempo con una idea en la cabeza: hacerme mi propio emulador de PCs obsoletos, empezando en XT. La virtualización por tanto no me vale; DosBox es inexacto y sólo apto para juegos de AT en adelante, y siempre y cuando se ciñan a la BIOS en determinadas cosas; PicoXT está seriamente limitado. Así que aprovechando estas pequeñas vacaciones que me he cogido me he puesto a ello.
Y he empezado a hacer pruebas con distintas ROMs. Para la BIOS de un XT hay aparentemente una de dominio público archiconocida, cuyo mensaje de copyright es "Generic Turbo XT Bios, (c) Anonymous", la cual es una taiwanesa que desensambló un tal Ya'akov Miles en 1987. Y también hay una modificación de la misma, por Jon Ρetrosky, llamada Turbo XT BIOS 2.0.
Para la emulación del disco duro del XT está la típica de Western Digital wdbios.rom, y para el video la et4000.bin (de una Tseng Labs ET-4000). También hay algunas sintéticas hechas para QEmu y tal, pero poco se ve por ahí volcado de hardware real.
Así que vamos a ver que tengo por ahí guardado, y vamos a ir volcando esas ROMs con el siguiente programita (ese A86 bajo DOS, hacía tiempo) que nos hace un snapshot del primer mega:
Mov Dx, Offset Nombre Xor Cx, Cx Mov Ah, 03C Int 021 Mov Bx, Ax Xor Dx, Dx Mov Bp, Dx Mov Cx, 32768 Bucle: |
Mov Ah, 040 Mov Ds, Bp Int 021 Add Bp, 0800 Jnz Bucle Mov Ah, 03e Int 021 Int 020 Nombre Db 'Prueba.bin',0 |
Un XT de verdad:
Este es un XT casi de verdad. 8088, 4.77 Mhz, venía originalmente con aquella CGA ATI de la cual ya he hablado en otros posts. La placa de abajo son simplemente los buses (todo va a través del ISA, pues va a su velocidad nativa) y a la derecha implementado un puerto serie, otro paralelo y el controlador de disco.
La placa del medio es la memoria, con su interfaz a bus. 640KB.
La de arriba contiene el ordenador: lógica, procesador, BIOS, PIC, PIT, DMA, PPI y las salidas de este último al teclado y altavoz.
Desgraciadamente la BIOS de esta placa ha sido la única ROM que no he podido extraer. No me arranca, el problema está en la placa de arriba; no sé si es el procesador o la ROM (la cual es ROM de máscara, no una EPROM, no la puedo leer sin más en una tarjeta de red).
Mi viejo XT:
Anda que no tiene años y ha sufrido abusos esta placa, pero es una campeona. Con todos ustedes, mi viejo PC. Un Inves X30Plus, realmente otro nombre para un ACER XTPlus. El microprocesador y buses de memoria (RAM y BIOS) son de 16 bits (doble de rápidos que los del PC original), pero no es un 8086. Es un NEC V30 (versión de SONY), el cual es como tres veces más rápido que un 8086 a su misma velocidad, y compatible con el 80186 (como un 286 sin modo protegido). Sin embargo nada de misma velocidad, este va a 10 MHz. Nótense las dos EPROMS, para las partes altas y bajas respectivamente de las palabras, que implementan la BIOS. Además tiene RTC, la interfaz de teclado es compatible con XT y AT, admite disqueteras de alta densidad, etc. Pero es un XT.
Desensamblando su BIOS precisamente es donde me he dado cuenta del tema ACER. Sabía del chipset, que tenían tachada la marca, pero no sabía que la BIOS fuese la misma. Aún así, hay una cadena "INVESTRONICA S.A." en un sitio inocuo.
Este PC me duró hasta la universidad, cuando me hice con un Pentium a 120Mhz. Tuve que parchear juegos como el Monkey Island 2 para que no detectase que no era un 286+, e incluso algún gestor de memoria exótico que paginaba a disco emulando EMS. Pero me duró lo que no está escrito.
Gráficas:
La de arriba es una auténtica joyita, es la que venía con mi PC. Un clon de una OTI VGA-800 basada en un OAK-037C. De nuevo, ROM partida; compatible con buses de 8 y 16 bits.
¿Por qué una joyita? Por sus emulaciones. Llamando la Int 10 con Ah=FF y Al='C', 'E', 'V', 'M' convertía la tarjeta en una CGA, EGA, VGA o MDA+Hercules ajustando las frecuencias y scans por hardware. Y su emulación era tan buena que funcionaban juegos como MoonBugs, Digger, etc.
La de abajo es más típica, una ATI VGA-800 (¿casualidad?) integrada por Compaq. Tiene los mismos chips que una VGA Wonder XL (ATI 28800-4, etc). Y es una de las pocas que, siendo de 16 bits, funcionan en un bus de 8. Por eso está aquí.
HDs:
Por último, necesitamos ROMs de las controladoras de disco XT.
Las de XT son las de la izquierda, no sé para qué he subido las otras del trastero. En fin. La de arriba es una Everex EV-340, compatible con muchos discos duros distintos, y que estuvo en mi viejo PC algún tiempo (a pesar de tener integrado su propia controladora en placa madre) junto con un disco duro de 42MB.
La de abajo es del primer PC que hemos visto, una LCS-6210D. Bastante limitadilla, pero interesante no obstante.
Las otras dos son para ATs (nótese el bus ISA de 16 bits) y no incluyen BIOS. Para quien le interese, una Seagate ST08A y una Western Digital WDAT-140, respectivamente.
Hale, ya tengo ROMs para trastear un rato con mi proto-emulador.
Érase una vez un televisor viejo, cosecha del 94.
Televisor sin audio estéreo, sin teletexto, sin entradas o salidas de audio o video, sin euroconector. Con mando a distancia, eso sí, y su entradita de antena en la parte de atrás.
Televisor que hasta el apagón analógico ha estado encima de la nevera de mis padres. Al que de vez en cuando le tuve que ajustar el control de ganancia automática, pues tendía a desintonizarse. Y por ello es que lo conozco un poco por dentro (lo sucio que está, al menos).
Lo suficiente como para saber que, al igual que la mayoría de cacharros, es una versión capada de algo superior. Basta con soldar unos cuantos componentes baratos y conectores (y apañar un sistema debido a un integrado distinto, acoplando un switch analógico para CVBS) para recuperar esa funcionalidad.
Y además tengo el manual de servicio técnico, nada difícil de conseguir pues este modelo ha sido montado por más de 20 fabricantes distintos, originalmente Philips (de hecho el tubo de rayos catódicos y la mayoría de integrados son de Philips, a pesar de ser Tecnimagen).
¿Por dónde empezamos? :9
Esta historia comienza cuando recibí la llamada de un primo mío diciendo que se le había estropeado el ordenador. Es un ordenador que tiene en su consulta (es fisio (mi primo)). Es un ordenador que dejó bajando cosas el fin de semana. Es un ordenador con más de 8 años. Y es un ordenador que cuando volvió el lunes estaba quemado.
Y por quemado quiero decir que la parte de atrás de la carcasa estaba chamuscada, que el ventilador de la fuente de alimentación estaba derretido, y que todo apestaba a humo. Y menos mal que sólo fue eso, pues estaba sobre una mesa de madera y rodeado de cosas relativamente inflamables. En cualquier caso, ahí fue cuando el ordenador ardió por primera vez.
Pero no fue ahí cuando llamó a Habi. Viendo que se había muerto la fuente de alimentación, decidió cambiarla por él mismo. Compró una nueva, la puso y, como era de esperar, no le funcionó. Así que empezó a trastear y trastear.
Y en uno de esos trasteos tocó el "botón rojo que se yo que no se debe tocar", según me contó luego por teléfono. Y al rato, el ordenador pegó otro pedo y empezó a soltar un humo blanco un tanto tóxico. En esta ocasión es cuando el ordenador ardió por segunda vez, y cuando se decidió a llamarme.
Cuando me lo trajo descubrí qué era ese misterioso botón rojo: el selector de tensión 230V / 115V. La fuente nueva estaba frita, los dos condensadores electrolíticos previos a la etapa de regulación reventados, todo mojado con el electrolito y lleno de trozos del interior los mismos. Ese era el humo blanco, me temo.
Tras varios trasteos variados, llegué a la conclusión de que la placa madre tenía fastidiado el puente norte, pues leía basura en el bus PCI (es una placa madre antigua, se comunica con el puente sur directamente a través del PCI). Así que me decidí a hacer algo que siempre había querido hacer y nunca había encontrado la ocasión: soldar por reflujo a lo cutre.
Así que con la base metálica de una vela del Ikea aplanada por debajo, un poco de alcohol de quemar, un mechero y el puente norte sin su disipador me dispuse a ello. Un ratito ardiendo encima, con el calor controlado. Ahí fue cuando ardió por tercera y última vez (al menos, en esta historia).
Y también fue cuando volvió a funcionar. Le volví a montar su disipador al enfriarse y, dado que el resto de hardware estaba intacto, el ordenador volvió a funcionar como antes.
El primer juego hentai que se publicó en inglés (y en "castellano" más adelante) fue el Cobra Mission. Pongo castellano entre comillas porque aunque están traducidos los diálogos del juego, el resto (menús, nombres de objetos, sistema de combate, ...) sigue en inglés. Incluso en su versión inglesa tiene ciertos problemas de traducción. Para más información, la wikipedia.
Lo que poca gente sabe es que originalmente era un juego japonés para PC98, con el mismo nombre. El juego para PC es un refrito del de PC98, con retoques y gráficos efectuados por unos chinos en colaboración con MegaTech (americanos). De nuevo, para más información, esta página.
A lo que por cierto, puedo confirmar que en efecto el tío de las fotos NO está en la versión de PC98, así como TAMPOCO las revistas o el servicio de mensajería. De hecho, el gráfico del último es originalmente el del funcionario del ayuntamiento del sur de Cobra (gracias a Z, por la traducZión).
Como decía en el post anterior, no fui capaz de sacar las imágenes en aquel momento. Años después y con el IDA lo acabé abandonando por aburrido, ya que tenía mezclada dos rutinas de descompresión con varias de volcado (diferentes modos de EGA y VGA).
Pues bien, me cogí hace poco la versión de PC98 y decidí no abandonar hasta conseguirlo. Y lo conseguí. Ahora puedo ver todas las imágenes, incluyendo los monigotes del mapa que bien me hubiesen venido para La Morgue:
Como se puede ver, los muebles son típicamente japoneses, los cambiaron en la versión PC. Tengo puesta la paleta de la ciudad, no la de las casas, por eso se ven así algunas cosas.
Pero lo mejor es lo que está escrito en inglés en el juego; hay joyas exponentes del síndrome "all your base are belong to us" como:
Hay muchos errores ortográficos debidos principalmente a una transliteración katakana -> romanji, como derector, ceef o coution en vez de director, chief o caution, que cualquiera que haya estudiado los kanas identificará.
El juego de PC98 está mucho menos censurado. En el de PC han pintado ropa, puesto objetos en medio, etc. Supongo que la censura americana es (o era) mayor que la japonesa. También han retocado alguna ropa, quitado el rubor que tienen todas las monigotas (independientemente de la imagen que sea), y cambiado carteles según les ha convenido. Como bien dice el autor de la página anterior, han cambiado completamente la trama (a lo que yo añado: incluyendo una sorpresa final con el enemigo final que NO tiene la versión de PC). No diré más.
Ahí van un par de fotillos que no están en la versión PC. Hay un gallifante de premio para el que sepa dónde han reusado una imagen de la primera:
Respecto al formato, es complejo; está orientado a componentes, entendiendo como componente una secuencia que incluye un byte por cada plano de la imagen (3 o 4, según tenga 8 o 16 colores), empaquetando 8 pixels.
Códigos de longitud variable, diccionario, operaciones de copia y operaciones raster, con bastantes casos. Pero cayó en un par de días, y tengo otro visor como el del Mugen.
Me falla la memoria; haciendo un post nuevo, me he puesto a buscar otro que creía haber escrito en este blog, cuando no lo hice aquí. En fin, copiaré una parte del mismo actualizada para que se quede en este sitio para la posteridad (la caché de Google).
El post es sobre un juego antiguo, una de esas historias interactivas eroge tan comunes en Japón y una de las pocas en ser traducidas al inglés. Su nombre es Nocturnal Illusion (Mugen Yasoukyoku).
Normalmente suelo pasar de este tipo de juegos, pues no suelen ser más que una excusa para mostrarte imágenes hentai. Sin embargo este tiene una muy buena historia de fondo y las escenas cerdas metidas como con calzador. Me dijeron que me iba a gustar y no se equivocaron. En esta línea de juegos de misterio (aunque con toque gore en este caso) podemos encontrar más recientemente a otros como el DiviDead (pobre perro ¿Saburo se llamaba?), pero eso es otra historia.
Le eché una ojeada por dentro, y me di cuenta de algo: no es más que una máquina virtual, los verdaderos scripts son independientes de la plataforma. Considerando los inconvenientes del juego (es un ejecutable de 16 bits NE, pero con un segmento de 32 bits para las operaciones gráficas) me decidí a analizarlo y generar de nuevo la máquina virtual.
Tal cual está no funciona en ninguna versión de Windows de 64 bits (pues ya no existe la máquina virtual de 16 bits). Tampoco es fácil debugearlo, pues está dentro de la VM de 16 bits, y la mayoría de los debuggers asumen siempre código de 32 bits, y aunque no sea así saltamos al código de la VM a la mínima. Sólo hay un desensamblador (que no debugger) que funciona bien, el IDA, con esta mezcla 16 bits / 32 bits.
Así que lo primero que hice fue desensamblarlo enterito, y después de agrupar código y datos, quitar basura, renombrar las cosas, identificar estructuras, etc, acabé con un librito de sólo 170 páginas en Courier de 8 puntos, doble columna y doble cara.
Más tarde, y tras buscar durante bastante tiempo, fui capaz de encontrar el original japonés para PC98.
¿Qué es un PC98? Es la abreviatura de PC-9801 y de los PC-9821, unas máquinas autóctonas de Japón fabricadas mayormente por NEC aunque hubo clones. Mientras aquí teníamos PCs, ellos tenían sus propias arquitecturas y no fue hasta la salida de Windows 95 que las empezaron a dejar de usar.
Estaban basados en x86 (8086, NEC v30 en principio; 80286 y 80386 más adelante, y después son básicamente PCs), con sus chips PIC y DMA pero en otras direcciones de hardware. Distintas BIOS con su soporte de kanas y kanjis y hardware de video y sonido dedicados. Aunque había otros competidores (x68000 (Sharp) y FM Towns (Fujitsu), por citar algunos), este fue el más extendido.
Tenían su versión de DOS y todo, similar al DOS/V pero con los kanas en BIOS, y usaban los mismos formatos de disquete y casi los mismos de disco duro (aunque con algunos cambios; hasta 16 particiones en vez de 4, unidad de arranque siempre A en vez de A ó C, arranque desde cualquier unidad (disquete, HD, MO, CD-ROM, ...), proceso de arranque estandarizado). Por eso es que es relativamente fácil entender sus programas, salvando accesos a hardware y llamadas BIOS.
En cualquier caso, las fases del proyecto con el Mugen son:
De momento está parado, hasta que me dé el yuyu algún día. Pero está bastante avanzado, funcionan perfectamente todos los menús y muchas partes del juego, y es compatible con los juegos guardados que se tengan.
Su VM trabaja con palabras de 16 bits, y tiene alineado su código y hasta sus datos a nivel de direcciones. Consta de unos 100 opcodes distintos, con funciones tanto de bajo como de alto nivel.
Particularmente me costó la rutina de decodificar las imágenes, una mezcla de códigos de longitud variable y diccionario rotatorio. Un formato japonés conocido simplemente como PI.
También hice una herramienta que manipula los archivos empaquetados, extrae, quita y pone ficheros, y navega por las imágenes y scripts mostrándolos.
Y ya vale de post, que bastante he escrito para ser una recapitulación.
Dibujos
Mi primer programa de dibujo venía con mi primer ratón (que me regaló mi hermana) para mi primer PC. Por aquel entonces, eran un artículo de lujo y costó lo suyo.
El programa se llama Mouse Painter y, al igual que el resto del software, estaba en alemán:
El programa utilizaba el formato PCX, de sobra conocido. En sus tiempos me hice mi propio visor en ensamblador, y más adelante uno más refinado en Turbo Pascal con soporte para más formatos. He aquí un pequeño collage de dibujos hechos con ese programa que aún conservo (y hay un premio para quien averigüe de dónde sale la tortuga esa):
Tiempo después llegó un programa de dibujo un tanto mejor, el Dr Halo:
El otro día intenté leer sus archivos de dibujo, y me di cuenta de que no aparece la información exacta del formato PIC en ninguna parte, sólo del CUT (para recortes). Además, no funciona bien en DosBox.
Una vez terminé mi propio programa conversor, me dijeron que sí existía algo de información en http://www.dal.kr/chair/ce/gformat/halo.txt, aunque es para una versión anterior, no listan los modos de video y tarjetas, no saben lo que hacen los campos de longitud y peor: no dicen cómo están los gráficos, se limitan a decir “I *do not* recommend trying to do any conversions to or from Halo .pic files. They are terribly sensitive to boards and modes thereof”.
En fin, ahí va otro de esos collages:
Y finalmente vino la época dorada: el Autodesk Animator y el Autodesk Animator Pro. A mi parecer el mejor programa de dibujo y animación, con permiso del Deluxe Paint, y facilidad de exportación para usarlos en mis propios programas (GIF, PIC en crudo, y documentación abundante de los formatos CEL, FLI y FLC):
Y aquí nada de collage, porque ya no era tan niño cuando hice los dibujos, y en este caso sí avergüenza. Pondré sin embargo un dibujo psicotrópico de una sobrina mía:
Sistemas de archivos
Supongamos que se tiene una imagen de disco, y que ese disco tiene formato NTFS. Aunque bajo Windows 7 puede montarse no me vale, pues es de un disco pocho. Así que me decidí y le añadí soporte NTFS (sólo lectura) a mi programa editor de imágenes:
Total: una tarde. Y funciona, en vez de quejarse y cascar como hace el Linux (loopback) por estar pocho el disco.
Paquetes RPA
Y por último una petición, un programa que extraiga archivos del formato RPA que usan ciertos juegos:
Viendo que es un formato propio del Ren’Py y viendo para qué vale ese programa me hago una idea de para qué se le va a usar. En fin.
En cualquier caso, hay una pequeña cabecera que incluye dos datos: el origen del índice y la clave con la que se encriptan las entradas de posición y longitud de los ficheros. Los ficheros están además con basurillas entre medias para confundir, y en versiones modernas con parte del principio del mismo dentro de los índices.
Los índices están al final, comprimidos con Deflate, y codificados con esa clave. En versiones modernas están hasta los 16 primeros bytes incluidos dentro, para que no funcionen los programas de extracción de imágenes y tal (a la vez que mantiene la compatibilidad con las versiones anteriores). Y todo en un streaming de los objetos Python (pickled).
Ya llegó mi nuevo pedido de DX. Esta vez tocaron algunas cosas para mi tallercito de electrónica y algunas gafas 3D.
Mi idea es usar unas de esas polarizadas con el monitor, aprovechando que el celofán gira 90º la polarización de la luz, para obtener una visión estereoscópica sin necesidad de recurrir a anáglifos ni nada por el estilo. Pero ya que estaban baratas, cogí entre otras las típicas con par rojo / azul.
Como seguramente sabrán, nVidia en sus drivers tiene soporte para sistemas estereoscópicos, a partir de una GeForce 8, para usar con gafas obturadoras de LCD y así enviar una imagen distinta a cada ojo sincronizándose con el refresco vertical.
Lo que ya es menos conocido es que tiene un modo “3D Vision Discover”, en el cual la propia tarjeta te monta el par en forma de anáglifo, corrigiendo colores, videos, etc. Así que decidí hacer la prueba.
El resultado depende un poco del juego pero es realmente bueno, y ya que funciona a nivel de drivers, compatible con casi cualquier juego o aplicación que use Direct3D. Particularmente estoy satisfecho con los resultados obtenidos con el Overlord, a pesar de no estar probado por nVidia, ni tener profile para él ni nada.
Hale, a dejarse los ojos. 8)
Esta es una imagen cogida de la web de cómo es la PDA que tengo con su peana, la cual es necesaria para cargarse, pues no se carga de USB:
¿Por qué no se carga de USB? ¿Por qué es el más de la mitad de alta que la propia PDA y aún más grande en profundidad? Esas son preguntas que siempre me hice. Así que me cargué la peana, y encontré una ínfima placa con el conector para la PDA, otro para el USB y otro para la alimentación:
El cable amarillo es un puente que le he hecho: de la alimentación del USB (igual que la de la fuente) al conector donde iba la misma. Ahora la PDA se carga de USB y sólo de USB (aunque se podría poner un diodo de baja caída pasé al final):
¿Por qué pasé al final? Pues porque con la fuente de alimentación externa y un conector USB hembra doble de una placa madre averiada puedo hacer esto:
Y alimentar / cargar cualquier cacharro USB directamente de la red, incluyendo si quiero la propia PDA.
¡Tachán!
A veces ocurre que es preferible expresar una determinada propiedad como condición sobre una expresión en vez de una sucesión de sentencias.
Veamos un ejemplo simple. Queremos comprobar que un cierto número X se encuentre entre otros dos cualesquiera A y B.
La forma normal de hacerlo sería ver cuál de los dos números A y B es el mínimo (y por tanto cuál el máximo, pudiendo ser iguales). A continuación se comprueba que X>=Min(A, B) y que X<=Max(A, B).
Sin embargo, esto puede expresarse con una simple fórmula y sin averiguar siquiera quién es el mínimo o el máximo. X está entre A y B si y solamente si (A-X)*(B-X)<=0. Esto bien puede ir como condición de un IF, al contrario que una sucesión de sentencias (en la mayoría de lenguajes imperativos).
Sea F(X)=(A-X)*(B-X). Es obvio que F(A)=F(B)=0. Y que para todo X entre medias, es mayor que uno y menor que el otro (+*- o -*+), luego el signo es siempre negativo. En el caso que sea mayor o menor que ambos, siempre será positivo (+*+ y -*- siempre es +).
Así pues tenemos una expresión booleana aplicable directamente en un IF, si estamos conformes con el coste de la multiplicación (respecto al de la llamada a una función, comparaciones e intercambio) y el resultado no desborda en rango. Si desborda, se usa Signo(A-X)*Signo(B-X) y arreglado.
Una función por el estilo más útil es Signo(A-X)+Signo(B-X), la cual nos devuelve 5 valores según el número sea menor que el mínimo, mayor que el máximo, el mínimo, el máximo o algo intermedio. Esto se deja como ejercicio para el lector.
Aplicado al caso anterior, X está entre A y B si y solamente si Abs(Signo(A-X)+Signo(B-X))<=1, lo cual es obvio si has hecho el ejercicio anterior.
Empecé a practicar este arte en mis tiempos con el Spectrum y su BASIC. Por aquel entonces el BASIC no tenía sutilezas como construcciones WHILE, REPEAT, ENDs para el IF y mucho menos procedimientos y funciones. Ni siquiera había etiquetas, pues cada línea iba numerada.
Y en concreto este dialecto no tenía ni un triste ELSE, mucho menos algo como un ON GOTO ni nada parecido. Sin embargo, tanto el GOTO como el GOSUB esperaban una expresión numérica. Así pues podía hacer por ejemplo un GOSUB 5000+500*A y saltaba a la subrutina adecuada, a partir de 5000 cada 500 lineas.
Se pueden ahorrar también de esta manera instrucciones IF, sabiendo que los operadores relacionales evalúan en {0, 1}. Es válido por tanto GOTO 1234*(A=9)+5678*(A=16), un LET A=27*(A AND 1)-42*(B=13) y cualquier expresión numérica que queráis, incluyendo incluso funciones definidas con DEF FN, etc.
El colmo de lo bizarro era generar en tiempo de ejecución una cadena con la expresión a evaluar y saltar a ella con GOTO VAL(A$), pues VAL convierte de cadena a número... pero esperando igualmente una expresión numérica en formato de cadena.
Ah, que tiempos cuando los lenguajes se parecían al ensamblador quisieran o no.
Encuentra las diferencias entre:
Y:
Bien. Este es, o mejor dicho era, el microondas que los antiguos propietarios de mi actual piso se dejaron. Medio oxidado, lleno de mierda, sin bandeja, requemado y con un plato para suplir la falta de bandeja (con un borde metálico que causaba unas descargas de la leche, y que por otro lado explica lo quemado y lo oxidado).
No obstante, probándolo bajo circunstancias normales, el micro funciona, y bien. Así que un montón de componentes funcionales para mi colección:
Ahora es cuando debo hacer una advertencia: nunca, Nunca, NUNCA, ***NUNCA*** te pongas a trastear dentro de un microondas sin haber descargado el condensador de alto voltaje. Es esa especie de cilindro de metal aplastado, con dos conectores cubiertos por PVC negro, en el centro de la foto. Aunque algunos como este tienen dentro una resistencia para auto-descargarse, lleva algún tiempo. Salvo que te guste jugar a la ruleta rusa, hazme caso.
Además he conseguido un transformador, diodos e inductores A.V., un sistema de ventilación que reciclaré como extractor de humos, un temporizador / selector con su timbre, sensores de temperatura, una bombilla, motores, relé, interruptores, sensores de temperatura, ... y el magnetrón, por supuesto.
Ya veremos si lo dejo tal cual para algo indecente o lo destripo para quedarme con los imanes toroidales. En cualquier caso, los microondas son una mina de componentes caros.
Hace tiempo solía escuchar música en un lugar de internet de cuyo nombre si quiero acordarme: Pandora.
Ya no lo hago, pues restringieron su uso únicamente para gente de EEUU (debido a las restricciones legales de la música). Se puede entrar usando un proxy estadounidense, pero no es lo mismo.
En cualquier caso, es un lugar en el que te van poniendo música similar a la que escuchas, y tienes la opción de puntuar si te gusta o no la nueva que te sugiere. De esa forma, vas creando un perfil de cada cadena de radio definida de las varias que puedes tener, y vas descubriendo nuevos grupos, etc.
El otro día me acordé de eso, y me acordé de que tengo bastante música sin clasificar en el disco duro. Así que pensé hacerme algo similar a eso, sólo que un poco más... friki.
Así que empecé a programar. Primero le hice al programa el que fuese capaz de extraer audio digital de cualquier medio, usando para tal fin DirectShow; ya se trate de una entrada de línea o micrófono, sintonizadora, CD, ..., archivo mp3, wav, ogg, wma, ..., avi, mpg, wmv, flv, ... En general, cualquier cosa para la que se tengan codecs. Personalmente, tengo codecs que renderizan hasta archivos mod, s3m, it, ...
Para medir cuánto se parecía una canción a otra, pensé hacer un análisis de frecuencias. Para evitar meternos con números complejos, pasé de transformadas de Fourier clásicas e implementé una DCT (discreta de cosenos, que es siempre real).
Divido la canción por segundos y transformo; en otra dimensión, se ponen esas transformadas, lo que nos da una matriz bidimensional. A continuación se escala para todas las canciones por igual, y además los valores se transforman logarítmicamente y reescalan también para estar en las mismas condiciones de energía.
Aquí tenemos un par de ejemplos:
El primero pertenece a la canción "Within Temptation - Angels.mp3". Como bien se puede ver, aparecen unas franjas verticales de energía decreciente por bandas. Esto es debido a la compresión mp3, que enmascara rangos de frecuencias según sea su respuesta al oído. El caso extremo es en la derecha del todo, donde ha suprimido todas las frecuencias altas (que el oído ya no oye).
El segundo proviene de una pista de un CD, extraído directamente: "Mozart - Symphonie N°25 in g-Moll - KV 183 Allegro con brio.wav" (sí, también escucho música clásica). Aquí el decrecimiento de los coeficientes de frecuencias es gradual, y no se anulan las altas. También, como se puede ver, es menos monótono (en el tiempo) y más rico (en las frecuencias).
¿Es correcto escalar en el tiempo para poder comparar más fácilmente? Ya os contaré los resultados. De momento, ahora estoy con la última parte; pensaba hacer una matriz de pesos donde cada valor ponderase la diferencia de esa componente, definiendo el error como la suma de todos éstos. Y ajustar estos valores según lo haga de bien o mal (lo cual es equivalente a una red neural de una sola capa).
¿Alguna idea constructiva?
Finalmente he decidido quitar la disquetera de mi ordenador, y poner un lector de tarjetas en su lugar. Como despedida, este post.
No os hablaré de la vida y milagros de Alan Shugart, pero sí diré que al tipo de interfaz de disco que se encuentra en los PCs se le llama Shugart. Aunque tiene un poco de modificación con respecto al interfaz SA400 original como ahora veremos, es prácticamente la misma cosa.
Originalmente, en la norma había provisión para 4 unidades de disco, y el cable era una cinta plana de 34 conectores, con todos sus conectores IDC. La unidad lógica de cada unidad de disco se elegía con unos puentes en la propia unidad. IBM en su implementación redujo el número de unidades a 2, separó la señal del motor para cada unidad y dispuso las líneas pares de forma que si se invirtiesen (cruzando parte del cable, pines 10-16) se seleccionase el disco sin tener que hacer puentes.
Por eso vienen todos los discos configurados por defecto como DS1 (unidad B), y para que sean DS0 (unidad A) deben ser conectados al extremo tras el cruce. Como cultura general añadiré que todas las líneas impares están conectadas a masa, como en un cable ATA de 80 pines (existe un mecanismo para detectar unidades con los pines 3 y 5, pero en la práctica casi nunca se ha usado).
Diferencias:
Pin SA400 IBM
6
DS3
Nada (o ED, 2.88 MB)
10
DS0
Motor DS0
12
DS1
DS1
14
DS2
DS0
16
Motor (¡todas!)
Motor DS1
Ahora llega la frikada; la hice hace algún tiempo, antes de las fiestas. Esta vez no hay fotos, pero es fácil de seguir. Hay par de pines interesantes, son el 30 (los datos tal cual los lee la unidad) y el 8 (marca índice). Esos pines son que usa el autor del Disk2FDI para hacer su cable, con el cual se pueden leer ambos a través del puerto de la impresora. No obstante, no todo puerto paralelo vale para eso, y bajo Windows o Linux es imposible al no ser SOs en tiempo real.
La idea es esta: hacemos una operación de lectura, pero pasamos de los datos (o fallos) que nos dé el controlador de disco. Lo que hacemos es capturar a una determinada frecuencia los datos a través del puerto de la impresora, y luego tranquilamente según sea la modulación separar los datos de la señal de los de reloj y listo. Pista leída a bajo nivel. Después resta leer el formato lógico de la pista, localizar sectores, volcar información de cada uno, etc.
Yo pensé hacer una interfaz Shugart completa controlada por un PIC y que volcase los datos vía USB, pero al final fui más cutre: usé los 3 puertos B, C y D de un 16F877A como un contador, para generar las direcciones A0-A23 de una memoria (usadas realmente A0-A19); usé una memoria estática de 100ns que tenía, una DS1265W, convirtiendo a 3.3V usando 2 resistencias como divisor de tensión, y conectando I0 así a la salida de datos la disquetera (tras pasar por un 1N4148, y lo conecto también al PIC; de esa forma puedo leer luego los resultados). Desperdicia 7 bits de cada byte, pero es muy simple. También para simplificar leo desde el PIC hasta llenar el Mb (independientemente de la velocidad a la que leo o de si la disquetera ha dejado de leer) e ignoro (ni conecté) la señal de índice.
Después basta usar de nuevo el PIC para mandar los datos por el puerto serie (software, puerto A; el UART hardware está en el puerto C, conectado a la memoria) y listo.
Dado lo cutre del invento, los resultados fueron bastante buenos. Pude leer los datos en crudo y vi que se correspondían a los datos que debería tener esa pista del disco (si bien al final no hice ningún programa que separase los datos leídos de la señal de reloj y reconstruyese la estructura del disco).
Y es que YA hay al menos un programa que hace eso; y que los disquetes están obsoletos; y que tengo proyectos más interesantes (bajo mi punto de vista). Supongo que esa es la lección de este post.
Hace poco descubrí un juego antiguo de estrategia espacial para Windows que no conocía: el Malkari; así que me dispuse a probarlo de inmediato.
(NOTA: Esto no es lo que parece... no es una reseña.)
No obstante, este juego no funciona en Vista, ni con modos de compatibilidad ni nada, así que me puse a experimentar con él. Haciendo pruebas, comprobé que tampoco era posible hacerlo funcionar en XP, y claro está tampoco en 2000. Sin embargo, en 98 y ME iba perfecto.
¿Por qué no funcionaba en núcleos NT? ¿Qué operación no válida era la que causaba su cierre?
Movido por la curiosidad, le metí un depurador. Cuando se produjo el error vi exactamente qué estaba ocurriendo: estaba accediendo (escribiendo) a una dirección de memoria en el proceso un poco más allá de 0x000B0000.
Por si no lo saben, el Windows mantiene cada proceso en un espacio de direcciones separado. Lo normal es que por la parte baja estén algunas tablas del SO, la aplicación empiece sobre los 16MB y de los 2GB (3GB si se usa cierta opción) en adelante esté el monitor de Windows, con gran parte del código y datos compartidos entre todos los procesos.
Una diferencia fundamental y poco conocida entre los núcleos 9x y NT es que los primeros además mapean la mayor parte de la memoria DOS por debajo del primer MB, compartida además entre todos los procesos. Así es más fácil y exacta la emulación del DOS y además proporciona una cierta capa de compatibilidad para aplicaciones de 16 bits y algunas de 32 antiguas. Por eso este acceso a la memoria no falla en núcleos 9x.
¿Y qué hay en esas direcciones? Pues ese el rango de direcciones de la memoria de video de texto monocromo, una MDA, para la cual no hay drivers de Windows y por tanto los accesos no se virtualizan; ni tampoco se bloquean, por estar mapeada la memoria.
En los tiempos del DOS era una práctica común usar una MDA junto con otra tarjeta gráfica para depurar una aplicación, ya que el rango de monocromo era siempre ignorado por la misma y quedaba libre para el depurador. Es la primera vez que veo esto en Windows, por parte de una aplicación, para sacar sus mensajes de depuración; con lo simple que es usar OutputDebugString o escribir los resultados a un fichero.
La solución es trivial, bien parchear el ejecutable o crear un lanzador que tras crear suspendido el hilo primario del proceso mapee la memoria con VirtualAllocEx. Sigue fallando tras eso por otras causas triviales y fácilmente corregibles, pero eso... es otra historia, como bien dijo el narrador de Conan.
Antes de empezar el post de hoy, debo corregirme en el de la CGA. Dije que el retardo de la señal respecto a los sincronismos se debía a las puertas y eso no es correcto.
Veamos una pequeña demostración; si una línea de barrido en NTSC son 15,75Khz = 15750hz, es decir 1/15750 = 6,349·10-6s = 63492ns, y suponemos unos... 640px, digamos 700 con sincronismos, esos nos da más de 90ns por cada punto; y en TTL tanto la familia SL como la HC (tal y como lo tengo ahora, para ahorrar energía) retardan unos 10ns. ¡Es que ni un pixel de retardo!
No obstante, la solución es la misma. Retardar o ajustar el sincronismo en la TV. Es la tarjeta, que es así.
El post de hoy tiene que ver con el modo MDA / Hércules de la tarjeta. Me dió curiosidad el ver si podía ser soportado, así que decidí probar el modo Hércules. Aunque sin mucha fe, ya que la frecuencia horizontal se nos sube a 18,425Khz (y la vertical nos baja a 50hz). En teoría, la luminosidad se inyecta por el mismo pin (el I de la CGA), así que debería verse en negro / gris. No obstante, le sigo diciendo en los jumpers que el monitor es color. Veamos qué pasó:
Varias cosas:
Y otra cosa retrofriki; a ver si para la próxima leemos disquetes en un PC a muy bajo nivel (por debajo del NEC765), incluyendo de Amiga y C64.
He decidido experimentar con esa vieja tarjeta CGA que tenía, y de la cual os hablé en otro post.
Así que para poder trastear con la tarjeta primero debería hacer algún tipo de adaptador para la señal de video, ya que no tengo un monitor CGA, y no se puede adaptar fácilmente a uno VGA como ya comenté en el otro post. Un monitor CGA es uno digital (16 colores, RGBI, niveles TTL), con 15,75Khz en horizontal y 60hz en vertical. Los mismos sincronismos que un televisor NTSC original, por eso es que casi todas las CGA llevaban una salida de video compuesto. Menos las de Europa, claro, que por aquí había PAL.
Primero pensé hacer un doblador de líneas (scanlines): ADC + memoria de doble puerto + DAC y circuitería anexa (en este caso al ser digital podemos ahorrarnos el ADC). Así podría generar 400 líneas en vez de 200 en los mismos 60hz verticales con lo que duplico la frecuencia horizontal, y así puede ser conectado a un monitor normal.
Por otro lado recordé que tenía una televisión que cogía NTSC o algo así; así que empecé a hacer un adaptador. Realmente es mucho más simple y barato, unas resistencias y poco más. Lo importante es que la TV sea capaz de entender los sincronismos.
Buscando por la red, vi que alguien se me adelantó:
Estaba haciendo un sistema con puertas XOR cuando vi este esquema. Como utilizaba las mismas resistencias que había calculado para el video (470Ohm para dar 0,7Vpp / 75Ohm) lo di por bueno y me puse a ello.
Tengo que añadir que esta persona asume (además de que la TV debe soportar frecuencias NTSC) que el pin 7 del conector de la CGA (reservado) da +5V. Este no es mi caso, por ejemplo; así que yo lo obtengo de una fuente de alimentación aparte. En las primeras CGA no era +5 sino +12, lo cual puede ser peligroso. Primer pufo.
Pues bien, una vez todo listo hice la prueba. En ese momento descubrí varias cosas:
¿Por qué salen las letras en magenta? Porque ha puesto la salida del verde en la patilla 4 del SCART, no en la 11. Segundo pufo.
Me puse a trastear con los sincronismos. Parece que están mal, y la TV utiliza los PAL. Como la frecuencia horizontal PAL es menor que la NTSC, resulta en un menor tiempo por línea, así que quedan más cortas y por tanto los textos quedan inclinados hacia la izquierda.
Si desconectamos el sincronismo vertical:
Sincronismo solo:
Entonces es cuando caí… me está juntando los sincronismos con resistencias, lo que equivale a una puerta OR, no una XOR. Y amplifica tal cual, sin tener en cuenta que los sincronismos de video son negativos, no positivos como en la salida TTL de la tarjeta. Tercer pufo.
Así que lo mandé al carajo. Volví a mi diseño original en torno a un 74LS86, adaptando los sincronismos con una resistencia simple de 3,3KOhm (no es necesario en esta TV, pero más vale prevenir):
Con los siguientes resultados:
Mucho mejor. La imagen está un poco corrida hacia la izquierda, por los retardos de los sincronismos (utilizo una segunda puerta XOR como NOT). La solución es trivial en este caso, retrasar las 4 entradas de la CGA con puertas.
Por seguridad uní el resto de masas en conectores, y apantallados. Y otra cosa tecnofriki para el blog.
Moraleja: NO uséis ningún circuito que veáis por ahí sin pensarlo previamente.
Como seguramente sabréis, hace algún tiempo me bajé unas 699 imágenes de disco, desensamblé un programa copiador para deducir el formato que utilizaba e hice un post sobre todo ello.
Bien; pues algún tiempo después de eso el autor de tamaña compilación de juegos se puso en contacto conmigo para pedirme el programa para convertir las imágenes. Al final decidí echarle una mano en el apartado técnico en su proyecto de recuperación de las imágenes de disco, y en eso estamos.
Tengo listas las imágenes de los juegos 0001-2100, 4016 en total convertidas a .img y pasándose por el antivirus en estos momentos. Según su contenido algunas de ellas están bien, pues son juegos que no se encuentran en otro sitio, son versiones boot, etc. Otras no tanto, pues no contienen más que un trozo de un .arj.
Pero este post no va sobre los juegos o el empaquetamiento, sino sobre el estado de los discos originales con los que se hicieron las imágenes.
Según he podido apreciar, muchas imágenes de las que estaban hechas con el EPLCopy fueron hechas porque no se podían hacer con Disk Copy Fast y similares, ya que el disco era ilegible.
¿Ilegible por las protecciones? Mayormente no; hay alguna, pero la verdad es que en casi todos los casos era porque los discos originales estaban defectuosos, tenían marcas de agua de otros copiadores o un formato mayor anterior que el programa copiador no había eliminado. También había algunos formatos no estándar, tanto en tamaño como en ordenación de sectores (interleave).
Así que hice un programa para modificar las imágenes de disco a bajo nivel (tocando incluso tamaños de sector, códigos de error, etc.), con el cual también pueden verse gráficamente las imágenes; aquí os traigo una pequeña selección. He pasado de mostrar errores, son los típicos de fin de pista, bandas de sectores, pistas enteras por demagnetización, etc.
El color verde es un sector que está bien, sin errores, en su sitio, coincidente con sus parámetros físicos y de 512 B. Si no cumple eso, estará amarillo. Y si directamente no se encuentra, rojo. Para diferenciar las caras del disco, pongo los colores claros y oscuros. Igualmente adjunto un volcado hexadecimal si la situación lo merece.
Primeramente una imagen de cómo el CopyWrite hace una marca de agua al disco en cuestión. Como bien se ve, añade una pista extra, y la rellena con esos sectores; los amarillos son defectuosos al final del disco, nada de protección:
Otro copiador y otra marca de agua, si bien me temo que éste es hardware. En ese sector extra del final de la última pista. Tiene la mala costubre de insertar sectores nulos de tamaño mínimo si cree que la separación (GAP) entre sectores no es estándar:
Veamos ahora parte del MegaProt de Titus, si bien está en un disco con un juego que no es de Titus ni tiene protección; tenía ese juego antes, y se copió encima; como esta pista está por encima de las estándar ahí se quedó. ¿Pretendía el autor insultar a los hackers diciendo que eran mujeres? Que no se entere la ministra Bibiana... Fernandez:
Otro despropósito aún mayor, esto es un disco 40-1-8 copiado sobre un formato previo 40-2-9 (160 KB en uno de 360 KB):
Por último, una protección de verdad. En efecto, hay un corte en el disco con laser en ese sector, justo antes del 3C 3C:
Y con esto doy por concluída otra exposición inútil más de las que tanto me gusta poner en este blog.
¿Cuál es la diferencia entre estas dos imágenes?
Solución: un trozo de papel de aluminio detrás del ordenador.
Moraleja: algún día los diseñadores de carcasas aprenderán el concepto de jaula de Faraday.
Últimamente vienen a mi blog personas desde Google buscando soluciones a problemas que me han ocurrido y que he resuelto. Así que este post va por mis futuros lectores; hoy vamos a ver cómo hacer funcionar una tarjeta de red inalámbrica D-Link DWL-G510 rev. C en Windows. Tarjeta en oferta en el Media Markt, para más señas.
Con los drivers que trae no he sido incapaz de hacer que se conecte a redes con Windows, desde 98 hasta Vista. Detecta bien las redes, mide todo bien, pero no se conecta. En la mayoría de las distribuciones de Linux ocurre algo parecido, sólo que no hay timeout y deja colgado el sistema entero en espera de obtener un IP.
Usando una WifiSlax se puede hacer funcionar, previo rmmod rt61 y modprobe rt61 (si no, como si no estuviese); después admite un iwconfig wlan0 mode monitor, se puede lanzar el airodump, etc. Funciona porque tiene unos drivers hackeados para poder poner el modo monitor entre otras cosas.
Pero centrémonos en Windows: no pongas los drivers que trae, ni siquiera con compatibilidad para XP SP2. Si los has puesto, quítalo todo. Ahora te bajas los drivers de RaLink, los instalas, y le pones manualmente los drivers de una RaLink RT61 Turbo Wireless LAN Card (por ejemplo) a la tarjeta detectada.
Luego configura la red con el programa de RaLink, no el asistente de Windows. Una vez configurado, se le da a conectar, se espera un poco (no se conecta) y ahora sí, se utiliza el asistente de Windows. Con los parámetros metidos a mano previamente sí rula.
Et voilà! Otra tarjeta puñetera que pasa por el aro.
En un departamento de Isolux, de cuyo nombre no quiero acordarme, no ha mucho tiempo que contrataron a un Gañán de los de nula informática, gañanucia superlativa y creimiento ingenieril.
El caso es que ese ser se trajo de su antigua empresa un programa para calcular cutremente el hormigonado de una presa. Un programa para DOS del año de la Polka, hecho en Clipper (una especie de extensión sobre el lenguaje de dBase III+, compilado sobre una máquina virtual). Un programa que, según pregonaba a los cuatro vientos henchido de orgullo, había hecho él.
Y aquí comienza mi historia; me dice el GF que tienen un problema, que no pueden sacar listados (lógicamente, ya que bajo Windows hay que capturar la impresión), y que se vendrán a ver si puedo hacer yo algo. Nosotros estábamos haciendo las documentaciones técnicas de una presa y su variante para ellos. Anteriormente ya les habíamos tenido que dar las áreas de las secciones cubicadas, tema que merecería un post aparte.
En cualquier caso, llegaron por la tarde el supuesto autor del programa y su jefe. Normalmente soy una persona poco empática, y nada más ver a alguien no siento nada (aparte de la repulsión que me causan los humanos, claro), pero este caso fue distinto, supe que su formación informática era nula. Y sus palabras y sus hechos me lo confirmaron.
El programa no sacaba los datos por pantalla ni nada porque estaba PROTEGIDO, algo que este proyecto de lechón ignoraba. Durante esa tarde me dediqué a lo que más me gusta: dejarle mal delante de todos y especialmente de su jefe. Al final admitió que el programa "lo hicimos los que estábamos allí"; el muy chorizo había borrado el archivo de la base de datos con los nombres de los creadores (y por eso da un casque el programa si le das a los créditos, no llegaban sus conocimientos a editar una sencilla BBDD en formato .dbf).
Conclusión: teniendo en cuenta que lo de la impresora era trivial, y que el supuesto fallo ocurría por el propio programa, siendo él el "programador" bien podría coger el código fuente y corregirlo, así que a mí que me dejen en paz. Ni que decir tiene que al final tuvieron que pasar del programa no sólo porque no daba los listados sino porque calculaba mal (la protección borra ciertas tablas).
Pero me quedé una copia, y ese fin de semana me dio por ahí y me lo llevé a casa. Teniendo en cuenta que estaba hecho en Clipper y tenía información de depuración, le di una pasadita por Valkirie, agrupé módulos y... código descompilado al 99%. Un poco de corrección, retirado de las dos protecciones que tenía, borrado de código muerto (hice un analizador), corrección de casques, del consumo de CPU vía OsLib, eliminado tema de impresión, añadido enlace a Windows, compilación con CA-Clipper 5.3b y tengo la aplicación funcionando bajo Windows perfectamente.
Pero esta no es la primera vez que abro algo relacionado con el curro. El mejor ejemplo de esto es el Cardim.
El Cardim es un programa que, hasta hace poco, no tenía versión para Windows (ahora existe una .NET) no sólo por el tema de portarlo, sino para que no se lo abriesen. Hay cientos de herramientas para desensamblar y depurar código "plano" de 32 bits bajo Windows, pero para un ejecutable de 16 bits en modo protegido la cosa está difícil, y requiere de alguien que se conozca y bien estas cosas.
Me llevó un par de tardes enteras retirarle la protección con pastilla a una versión que me bajé del Emule que alguien había puesto para ver si alguien era capaz de abrirlo, el IDA y al Turbo Debugger para modo protegido (nada de Soft-Ice) se portaron como campeones. En breve, un conocido nos trajo la versión 2000 con soporte para DXF y estuvo lista en un par de horas. Detalle curioso: está hecho en Borland Pascal (no hace falta decir más).
La diferencia con el anterior es que en esta ocasión fue el jefe el que me lo propuso; teníamos que hacer un trabajo de señalización, era imposible de hacer por los delineantes, el programa costaba entre kilo y medio y tres kilos (y recordemos: es una patata en DOS que sólo hace carteles), y estaban en juego los beneficios de diciembre.
Así que pudimos repartir beneficios y además me llevé un plus por reventarlo. ¿Cuál es la moraleja?
¿Pagar 200€ por una batería para un PC obsoleto? Buscando mejor las encontré por 100€ desde un sitio sospechoso que vi en Canadá y por casi 300€ desde otro de Inglaterra. Añádansele gastos de envío y puñetas varias.
Sale caro, así que como esta ya está jodida he decidido abrirla, mirar las celdas de litio que contiene e intentar sustituirlas por otras nuevas, iguales o compatibles.
*ATENCIÓN* Esta batería, como todas las que se usan actualmente, es de litio. El litio es peligroso; por un lado contamina, con lo que debe ser depositado en lugares de recogida, y por otro lado, si una celda de litio se sobrecarga más allá de su capacidad EXPLOTARÁ violentamente. Y lo mismo puede pasar si se calienta de más, así que nada de quemarlas en una fogata. Resumiendo: si no sabes lo que haces, no intentes hacer nada parecido.
Una vez abierto el paquete vemos que son ocho celdas individuales US18650GR: capacidad de 2200 mAh, voltaje nominal de 3,788 V.
En esta imagen se ve mejor: primero se agrupan las celdas de dos en dos en paralelo, para doblar la corriente (capacidad), y luego todas en serie para cuadruplicar la tensión.
El paquete exterior anuncia: 14,8 V, 3200 mAh, valores más conservadores que los teóricos 15,152 V, 4400 mAh resultantes.
El pequeño circuito que vemos en la foto se encarga de varias cosas. Le dice al ordenador el modelo de batería que es, la carga que le queda, si está en carga o no, etc. Pero sobre todo, regula la corriente que entrega la batería (el litio se sube a la parra a veces) y deja de cargar cuando la batería ya está cargada, para que no explote.
Fin del capítulo 1
Hace poco me ha dado otro de mis yuyus. Me he vuelto a instalar el Dungeon Keeper, el primero, el original, el único e inimitable.
Funciona perfectamente en vista, al contrario que XP. Sólo tenía un pequeño detalle: no se veían los videos, el monitor se salía de rango.
Así que nada, me hago un programilla para comprobar los modos de video, y veo que desde 320x200 hasta 400x300 no funcionan, para cualquier frecuencia vertical.
"Ya estamos", pensé. Me bajé drivers nuevos y pasé de la 163.leches a la 169.mierdas.
Pongo el DK… ¡y no funciona! Trozo de pantalla negra (la ventana de fondo, para DX, bajo un thread dedicado que tarda en cerrarse) y adiós.
Lanzo de nuevo el programita, y esos modos han desaparecido. Entonces lo entiendo todo: no están duplicando scanlines, luego claro está, es imposible lograr 320x200 en cualquier monitor de EGA para arriba, modo que utiliza el juego para los videos, que por cierto, son smacker.
"¿Pero qué dices? Yo he jugado juegos 320x200 en mi ordenador", dirán algunos. En efecto, pero el monitor NO lo soporta, es la tarjeta gráfica la que lo arregla.
Un cálculo rápido nos dice que 320x200 requiere una frecuencia horizontal de unos 15Khz; mira el manual de tu monitor, como cota inferior tendrá 30Khz o así.
En los tiempos de la CGA, el monitor tenía las frecuencias de una televisión NTSC, de ahí los 60hz y los 15KHz. Pero era una frecuencia fija.
Para evolucionar y permitir más modos hay que usar una frecuencia variable. Y eso implica estar entre ciertos valores. Para hacer los modos de poca resolución, la BIOS hace que la tarjeta gráfica duplique scans: el modo 320x200 es realmente 320x400, sólo que cada scanline se envía dos veces: doble pixel clock, misma frecuencia vertical -> doble frecuencia horizontal, y pasamos de 15 a 30Khz, valor permitido por casi cualquier monitor.
Volviendo al problema con los drivers, esto rompe la compatibilidad con muchas aplicaciones antiguas (vale, juegos retro). Mi primera solución fue añadir a mano los modos de video en el registro, pasando de tocar el .inf del driver y reinstalar. Reinicio y funciona, volvemos al caso de las 163.leches. Funciona, pero fuera de rango.
Finalmente, miro las versiones beta y me bajo la 174.pollas. ¡Aleluya! Han vuelto a poner la opción de añadir modos de video a mano. Pongo los valores físicos para el hard del modo 640x480x75hz pero los lógicos del de 320x200... No sólo funciona, sino que estira el trozo de pantalla para que ocupe todo. Qué detalle, permiten spanning negativo automático. De nuevo ese DK de moda y videos a pantalla completa.
Y todo esto porque no me dan la opción de doblar scanlines en el secuenciador (puerto 3C4h; índice 1, bit 3). De paso añadí 320x240, 640x400, etc. basados en 640x480 y 400x300 y tal basados en 800x600.
Hace tiempo, buscando imágenes de disco del Knight Force para poner los archivos en sus respectivos discos originales, me encontré con una cierta recopilación. Os invito a mirar el siguiente link: [link].
Alguien se ha tomado la molestia de recopilar todas esas imágenes (y otras muchas más que todavía no ha publicado) de discos de juegos de los años del DOS. Me picó bastante la curiosidad, tenía una ADSL en el curro muerta de asco, una cosa llevó a la otra...
Al grano: en efecto esos archivos contienen las imágenes de disco, y estas son correctas. Sin embargo, están hechas con un programa raro, el EPLCopy (de uso interno de IBM y que no conocía hasta hace poco), nada de CopyWrite, DCP, o una simple imagen RAW en crudo. Si hay craqueos en los juegos, no hay disco llave, luego entonces deben ser imágenes estándar, luego lo lógico es usar RAW.
Sólo se encuentra por internet ese programa (v4.21 y v5) en una subida del propio autor a GigaSize. Descarga que me casca siempre que intento bajarla.
Con la v4.21 se baja bastante, así que uso un gestor de descargas, le interrumpo, renombro a .zip y arreglo con el WinRar. Se puede extraer el ejecutable.
Como dice el autor, sólo se puede grabar con el programa a disco, y eso bajo DOS. Ningún programa entiende este formato raro.
¿Qué hizo Habi a continuación? Lo que no haría nadie en su sano juicio: tratar de averiguar el formato del fichero estudiando el programa a partir de su desensamblado.
Pero primero hay que quitarle las compresiones y protecciones (*ays*). Cups, Tron y el debugger del DosBox (versión desarrollador, claro), y queda medio listo para empezar. En el Ida hay que reconstruir el segmento de datos y se puede empezar a trabajar.
Está compilado en MS C, de las primeras versiones. Buen programador, mal compilador; el hombre ha hecho trucos a nivel de FDC, BIOS y DOS todos juntitos, el compilador ni las optimizaciones más básicas.
Pero finalmente, tras dos días, he sacado el formato. Al final del fichero un pie opcinal de 512B con la descripción del disco, seguido de otro variable (18B normalmente, depende de la versión); al principio una o más cabeceras de 80B (normalmente una) CODIFICADAS con una tabla rara. Después, todos los datos están comprimidos con un simple run-length, con el código F1 como prefijo y alguna modificación en las repeticiones.
Estos datos están separados por pistas de disco; cada una empieza con una cabecera de al menos 80B de descripción con los datos de los sectores y después todos los datos en crudo de las pistas. ¡Por fin!
Programita en Delphi, abrir el resultado con mi editor de imágenes o el WinImage o lo que sea, y arrastrar afuera. Ya tengo entretenimiento para este finde con mis emuladores.
...de la ganadería de L. Premio merecido por sacar en algo legible los datos de un antiguo disco, 3" / PCW / LocoScript.
Cena 1:
Esta es la fase hardware. Para leer este disco de 3" usamos un Spectrum +3 (que tiene disquetera de 3" y un µPD765 como controlador), al cual se le ha acoplado una disquetera de 3½" de PC para intercambiar los datos.
En principio el disco recalibró varias veces mientras lo analizaba bajo +3DOS, pero al final se leyó bien. Normal, pues llevaba mucho tiempo sin leerse. En vez de copiar los ficheros al otro disco, opté por hacer una copia sector a sector y luego volcar la imagen en el PC con mi editor de imágenes de disco, para no perder datos. Me dí cuenta de que el tamaño libre no se correspondía con el teórico del disco, esto lo veremos con más detalle en la siguiente fase.
Otra ventaja de la imagen es que la lectura es secuencial, con lo que eliminamos posibles time-outs y fallos del disco (que tiene muuuchos años) bajo un acceso aleatorio.
Cena 2:
Las imágenes por sí solas bastarían para trabajar con esos datos bajo un emulador de PCW, como Joyce o MESS con su driver. Pero nos interesan los archivos, en PC, en algo legible.
Teniendo en cuenta que estos están clasificados en grupos (incluyendo el limbo, posiblemente la primera papelera de reciclaje de la historia) del LocoScript, y éstos están basados a su vez en los usuarios del CP/M, además de existir archivos ocultos y de sistema, usamos de nuevo mi editor de imágenes de disco sobre las imágenes anteriormente creadas. Si los hubiésemos copiado tal cual a otro disco hubiésemos perdido toda esa información.
En cualquier caso se extraen, se borran los de arranque / grupos / configuración del propio LocoScript y luego añadimos la extensión .abj (por ejemplo) a todos los ficheros para que no se confunda el Windows.
Ahora sólo nos falta convertirlos a algo legible.
Cena 3:
Hay por ahí varios conversores de LocoScript a algo, y todos cascan o son de pago. Finalmente me decanto por WinConv, con sus modulitos para LocoScript y RTF.
Es de pago, pero dan una versión demo, la cual sólo convierte hasta 25 archivos, y nunca más de 10.000 bytes en cada uno. Siendo el programa de 37KB, sin compresión / empaquetado / protección, es desprotegido en dos minutos y me salto ambas restricciones.
El programa funciona bien. Sólo tiene una pega: se come unos caracteres del principio de los ficheros. Así que los miro uno a uno, contrastando con el volcado hexadecimal del paso anterior y se corrige.
Moraleja:
Una hora del paso 1, un minuto del paso 2 y media hora del paso 3 = 1:31; y 1:31 de mi tiempo bien vale tres cenas.
Jugando a juegos antiguos, encontré mi querido Alley Cat.
Juego que funciona perfectamente incluso bajo XP, por sus rutinas de retardo / sincronismo. Mejor no probarlo bajo DosBox, porque no hace una emulación de los ciclos de cada instrucción.
Me dio el punto y me puse a desensamblarlo. Y me di cuenta de que las rutinas gráficas encargadas de poner la paleta de colores eran dobles, y se discriminaba por que el valor de una variable valiese FD; una variable que se inicializaba con el valor de F000:FFFE (FFFFE), el machine ID. ¡Estaba tratando el caso especial del PCJr! Y de una manera no compatible con el Tandy 1000.
Esto merece una explicación; no entraré en detalle sobre la historia de los PCs. Sólo decir que después del PC (Agosto 1981) y el XT (Marzo 1983), en IBM decidieron hacer un ordenador más cutrillo y tal, orientado para la familia en vez de los negocios: el PCJr (Noviembre 1983).
El ordenador en cuestión fue una ruina. Aunque tenía gráficos de 16 colores (una CGA mejorada), era bastante incompatible con el PC, más lento debido a utilizaba el reloj del sistema para el refresco de la memoria, tenía un teclado infame (e inalámbrico), era caro y sobre todo: los ordenadores de 8 bits YA lo superaban en gráficos, precio y catálogo de juegos. No digamos ya los de 16 bits como el Amiga.
Por su parte, Tandy decidió hacer unos clónicos orientados al uso doméstico. Como había salido hace poco el PCJr decidió hacerlos compatibles con él. Una semana antes de su lanzamiento IBM anunció que renegaba del PCJr, así que Tandy cambió toda la publicidad de su ordenador a "MS-DOS compatible", lo cual no era falso.
Pero volvamos al Alley Cat.
Experimenté con el DosBox. Tanto en modo PCJr como en modo Tandy con un ejecutable parcheado el resultado que tenemos es:
Probé en Tandy con el parcheado porque dicen que la emulación de PCJr está al 50%. Pero nada, siempre saca el juego esa paleta, lo cual contradice el código del juego, el cual para cada habitación utiliza una paleta distinta. Y no es esa, además.
Utilizando el MESS para emular un Tandy 1000, con el ejecutable parcheado:
Esto sí se corresponde a los colores definidos en la tabla para la pantalla 0, la presentación.
Sé que se hicieron muchos juegos que detectaban Tandy 1000 y tenían gráficos y sonido mejorados, pero nunca había visto uno exclusivamente para PCJr.
(Nota: Todos los gráficos son en RGB; paso de video NTSC compuesto.)
(Moraleja: El DosBox es una mierda para cosas antiguas; incluso PicoXT (29Kb de emulador) le da mil vueltas.)
Hoy me he puesto una disquetera de 5 ¼ para pasar unas imágenes de arranque raras. Qué recuerdos.
Recuerdos de cuando un gañán, llamémosle D0, intentó copiar mi disco original del Mad Mix Game sobre uno en blanco. Pues bien, lo hizo al revés, borrándome mi juego. Me dio el yuyu y hoy lo bajé de internet y lo puse en su disco original, reparando el daño de forma simbólica.
Esta otra es mía en parte. Usando un programa que cacheaba las disqueteras para ir más rápido y una disquetera defectuosa que NO informaba cuando había cambio de disco y que se pasaba por el forro la protección del disco, al hacer el cambio del disco 2 al disco 1 me machacó la entrada del directorio principal de otro juego original, el Knight Force (EGA / VGA). Aunque tenía todos los archivos en un disco de 3 ½, no sabía cuáles iban en el primer disco, y era un coñazo mirar con un editor hexa. Hace no mucho, desensamblé el juego (lo dije en otro post), lo desprotegí (ya funciona desde donde sea), miré dentro del ejecutable para sacar las listas de archivos por disco, y de nuevo hoy he podido restaurar el juego.
Y hablando de esta disquetera, también tiene su historia gañana. Había otro personaje, al que llamaremos D1, que me la pidió para pasar unos discos viejos que tenía. Aparte de que tuve que pedírsela VARIAS veces, me la devolvió rota y sin el frontal y la llave de apertura / cierre. Nada que no pueda arreglar con un soldador de estaño y unos alicates, respectivamente. Aunque además de esto le friese un disco duro a mi hermano invirtiendo el conector de alimentación (no sé cómo lo hizo, sólo tiene una posición) y le inutilizase la información de dos discos duros a mi sobrina (nada que no pudiese arreglar), en el fondo me da pena.
Antes de que alguien lo pregunte, D0=D1, pero son distintas personas; parece maldito el nombre de Daniel (uuups, lo dije).
En cualquier caso, hoy he podido sacar una imagen de un juego de arranque (nada de DOS) que no se encuentra por la red; ni más ni menos que La abadía del crimen. Usando el cable de la disquetera invertido, porque el diseñador de la placa madre de mi ordenador (perfecta en todos los demás sentidos), decidió ofrecer sólo soporte para una disquetera y aprovechar los otros dos terminales del IT8718F como conexión a otro sensor térmico (gañanada). Enviaré la imagen a los de http://retrograde.trustno1.org/, que se la merecen. También saqué imagen de los discos de sistema de un PC1512, con su DOS modificado y su GEM.
Y además he podido jugar a algunos juegos ochenteros de arranque en mi flamante core duo (no sin antes conectarle el beeper, cosas de un montador gañán que además montó el disco duro en SATA1 en vez de SATA0). Casi todos van perfectamente, algunos fallan sólo en la intro. Qué recuerdos.
Hace poco retiré del trabajo un ratón óptico al que no le iba bien la ruedecilla. Por curiosidad lo abrí, y debo decir que es una de las cosas más baratas que he visto. La parte de la ruedecilla es un sensor mecánico realmente cutre. El resto, dos integrados y un LED.
Este es el ratón:
Por curiosidad miré los integrados. Y me pareció muy curiosa la funcionalidad del OM01, es una versión clónica y capada de un ADNS-2051. Este tipo de integrados contienen un sensor CMOS con el que obtienen una imagen unas 1700 veces por segundo y calculan el desplazamiento del ratón comparando.
Lo gracioso es que tienen un puerto serie SPI para mandar y recibir comandos. Y que uno de ellos es volcar la matriz de puntos.
Como todo va a niveles TTL, la solución obvia es conectarlo por el puerto paralelo. La programación no fue tan obvia, ya que mi ordenador es demasiado rápido para acceder directamente, y los sistemas operativos modernos no tienen un control del tiempo fino, pues no son sistemas de tiempo real.
Este es el ratón hackeado:
Aquí enchufado al ordenador y a una fuente de alimentación externa:
Y aquí una lectura del papel que tengo debajo; es un "JA" de Javier (subí un poco el plástico con el sistema óptico, para que cogiese más área):
Otra cosa menos.
He visto que en este sitio detallan algo parecido, pero con un ADNS-2610, que es un chip de verdad y no esta cutrería. Un conjunto mejorado de comandos, un chip compacto con sólo la interfaz serie, y una matriz de 18x18 en vez de 16x16. Aparte de ser Agilent y no un cutre OM01 sin marca.
Por otra parte, yo no lo extraje y conecté con 4 hilos, sino que acoplé otro conector al ratón, para que siga funcionando a la vez. Lo alimento con dos hilos (enchufados a los mismos sitios que la alimentación PS/2) y otros 3 los uso para el puerto serie (GND, TIO y TCLK) y son los que van al paralelo del ordenador.
Este es el ordenador de Habi con algo instalándose:
Aquí corriendo una aplicación:
El mando a distancia del PC (de regalo con la AverMedia) es grande, negro y con muchos botones; pero tengo este otro de aire acondicionado que brilla en la oscuridad:
Este post debía ser especial.
Por ello descarté la modificación del sistema de video del +3, descarté la visita al SIMA, descarté las fotos de Sandito.
Del mismo modo, descarté estos dibujos, y también algunas paranoias.
Debía hacer algo tipo resumen.
Y qué mejor que esto. El que tenga ojos que vea.
Hace mucho tiempo hubo un sistema operativo que funcionaba en muchas plataformas distintas. Ese sistema operativo era el CP/M.
Sus requerimientos básicos eran:
En el caso del Spectrum no hubo una versión del CP/M hasta el +3 (por el cuarto requerimiento), y encima tarde y un poco capado. Creo que hubo una versión en BetaDisk para algunos clones de Europa del este o Rusia, pero no estoy seguro.
¿A qué viene todo esto? Pues que teniendo ahora una unidad de 3½" en mi +3, he creado una imagen de disco de 720KB (entera a $E5), he modificado el primer sector creando los 16 bytes primeros para identificarlo y copiado los restantes 240 del sector de arranque del CP/M, y copiado todos los ficheros de ambas caras de los discos.
El resultado: ¡todo el CP/M en un solo disco, y encima con más de la mitad libre!
Además, navegando por internet encontré:
http://www.cpm.z80.de/ Donde tienen los códigos fuente. (:!)
http://www.secarica.ro/html/cp_m_plus_for_plus3.html Donde este tío ha compilado los parches para el año 2000 y otras mejoras.
Así que ahora tengo mi CP/M en un solo disco y actualizado. Ahora miraré de cambiar la unidad del RamDrive por M en vez de C, y si me siento poderoso crear un driver GSX para spectrum (y así poder ejecutar el DrLogo).
Algoritmo 1:
Acto 2:
Hacía tiempo que quería hacerme un programa para editar imágenes de disco. Así que me puse a ello. Lo he hecho muy modular, con mini-drivers a tres niveles.
Apartado 3:
Ejercicio para el lector: Enumérense las posibilidades de esto.
Algunas personas se han interesado por el adaptador de puerto serie que hice para el Spectrum.
Lo primero que tengo que decir es que no es sólo para usar el Spectrum como terminal, es un puerto serie bidireccional completo. Se pueden transferir datos o programas (es lo mismo) desde un PC al Spectrum y viceversa, y de hecho, no tiene porqué enchufarse a un PC vía cable de modem nulo como hice en el post anterior.
Hoy he hecho un experimento distinto, le he acoplado un modem externo viejo que tenía.
Simplemente escribiendo un LPRINT en el Spectrum con el comando del modem para marcar por tonos mi propio teléfono...
...el modem levanta, espera tono, marca, espera señal y cuando comunica le manda al ordenador el código de error.
Tampoco tiene porqué ser un modem, valdría una impresora serie, un ratón o teclado no USB (adaptando), un grabador de EPROM, ... lo que sea.
Se podría hacer un programa (ensamblador) con unas, digamos, 300 lineas para controlar el modem (rutinas), 50/60 para el protocolo PPP, y un TCP/IP mínimo (ICMP, IP, UDP, TCP) en otras 500 o así; pero yo no lo voy a hacer. No tiene sentido, hoy en día.
De hecho, tampoco lo usaré de terminal, ni para transferir programas ni para nada. Hice esto igual que el adaptador para euroconector o el de impresora (paralelo): para cumplir un deseo que tuve de pequeño, eso es todo.
Siempre hubo algo que quise hacer, y es conectar el Spectrum con el PC via puerto serie sin cambiarle el conector BT 630W al Spectrum.
Encontrar esos conectores es casi imposible en España. Pero hace tiempo, un amigo me dio un par de adaptadores que, aunque no eran exactamente iguales, podían adaptarse.
Ayer me dio el venazo y, después de cortar con cizalla, limar, lijar, retirar espadines, rehacer surcos, poner alambre de las centralitas telefónicas, cerrar, sellar con masilla epóxica, soldar, y poner conectores he acabado con esto:
Está montado sobre un trocito de placa de esas de tiras. Además de un enchufe DE-9 con las señales TIA-232 (RS-232) tengo pensado ponerle un conector DIN para el MIDI y otro de pines para trastear o para el auxiliar (ya que el enchufe es el mismo por el lado del Spectrum).
El manual del Spectrum te da las conexiones, pero hay que tener en cuenta que son a las que deben conectarse. Si quieres hacer un puerto serie normal, debes saber que son justo las contrarias. El conmutador es para conectar la línea 4 con el conector o con la 6, para que el flujo dependa o no del hardware (y no la 5, como dice el manual).
Después de probar varias combinaciones de comunicación, logré esto:
Para quien le interese, diré que la comunicación desde BASIC es 8 bits sin paridad y un bit de parada. Sabiendo esto, fue fácil obtener en el PC vía HyperTerminal:
Los programas usados empiezan por:
10 FORMAT "P"; 9600
O:
10 FORMAT LINE 9600: FORMAT LPRINT "R"
Dependiendo del modelo de Spectrum 128K (el primero para 128 y +2, el segundo para +3, +2A/B). En el caso de 9600 baudios sobrarían esas instrucciones de formateo, pues es la velocidad por defecto del Spectrum. El primero, para recepción, es:
20 OPEN #4, "P"
30 PRINT INKEY$ #4;
40 GOTO 30
Y el segundo para emisión:
20 LPRINT "Hola"
Y una imagen de regalo:
Me ha dado por la iluminación.
Este viernes me traje del curro las tripas de un scanner viejo, para ver si podía aprovechar algo. De la placa de control dos chips de RAM estática, el resto no vale gran cosa; de la fuente de alimentación unos condensadores y diodos, principalmente un condensador de poliéster para 250V.
En la parte óptica he pasado del sensor CMOS y anejos, y he salvado el inversor y los cátodos blancos de iluminación. Y aquí los tengo funcionando:
A ver si me traigo un cilindro de cartón de los que llevan dentro los rollos de papel A1, lo forro de albal y me hago una lamparita catódica. La luz blanca es excelente, se nota que el cátodo tiene bien graduado el punto blanco.
Para que os lo creáis de una vez:
La fuente de alimentación del post anterior funciona, no hay que usar transformadores, es barata, segura y estable. Y tengo mi masa en el neutro de la red, puedo conmutar triacs, etc.
Y para los que siguen sin creerse los precios de los componentes:
2 zener 3V9 1/2W, 2 1N4007, 10 resistencias, 2 condesadores de 470uF (25V) y 2 de 330 (16V) me han salido hoy por 43 céntimos.
Creo que lo tengo; ya tengo esa fuente de alimentación para alimentar a los pics de la domótica casera directamente desde la red, tomando como masa el neutro:
Metiendo un osciloscopio en R1 para ver la variación del voltaje (2V/div) respecto del tiempo (100ms/div):
¿Alguna duda?
Me he propuesto hacerme esos controladores domésticos que mencioné en el post nº 4 (si no lo has visto, mira el archivo, que para eso está).
El paso esencial es el interconectar el ordenador a la red montada por los cables de la luz, para lo cual pensaba usar un PIC que tuviese UART (USART) para comunicarse con el PC, y llevar por software el protocolo que tuviese esa red (en otro post os contaré el que he diseñado, porque X10 es una guarrería).
De nuevo hoy he ido a comprar mis chucherías, incluyendo un PIC 16F628A (más barato que el 16F84A, y con un montón de mejoras y cosas extras), y un MAX233 (para convertir los niveles de voltaje TTL - RS232) por el que me han clavado un poco más del doble del precio del PIC. En fin, al menos no necesita condensadores externos, como el MAX232.
El programa ha llevado un poco, debido al sistema de interrupciones del PIC para el envío. Al final, sólo uso interrupciones para la recepción; recepción asíncrona y envío síncrono. Más que de sobra para lo que necesito. Hacer que haga un saludo al principio, y un eco de los caracteres recibidos, invirtiendo las mayúsculas y minúsculas para saber que está funcionando, y a correr.
El código es algo así:
;Esto es una prueba del USART para el pic 16F628A
list p=16f628a
include <p16f628a.inc>
SalvaW equ 0x20
org 0x00
goto Inicio
org 0x04
btfsc PIR1, RCIF
call RxInt
;Otras interrupciones
retfie
RxInt:
movwf SalvaW
movfw RCREG
xorlw 0x20
call Envia
movfw SalvaW
return
;--------------------------------------------
Envia:
bsf STATUS, RP0
EsperaEnvio:
btfss TXSTA, TRMT
goto EsperaEnvio
bcf STATUS, RP0
movwf TXREG
return
;--------------------------------------------
Inicio:
bsf STATUS, RP0
movlw B'00100100' ;TXSTA: TXEN, BRGH
movwf TXSTA
movlw D'25' ;SPBRG: 9600 baudios
movwf SPBRG
bsf PIE1, RCIE ;PIE1: RCIE
bcf STATUS, RP0
movlw B'10010000' ;RCSTA: SPEN, CREN
movwf RCSTA
movlw B'11000000' ;INTCON: Hablito interrupciones (general) y periféricas
movwf INTCON
movlw 'H'
call Envia
movlw 'o'
call Envia
movlw 'l'
call Envia
movlw 'a'
call Envia
movlw D'13'
call Envia
Bucle:
goto Bucle
end
El circuito de prueba y el resultado:
Sale "Holala" en el HyperTerminal porque intenta emular un terminal con protocolo definido y se hace un lío con los caracteres de control (retorno de carro en este caso). Oh lalá, es una señal.
Ya falta menos…
Cuando cuento que hago tal o cual cosa pareciera como si esta se hiciese siempre a la primera, como si nunca me equivocase. Nada más lejos de la realidad.
Hoy por ejemplo, tras probar el programa del PIC en el emulador (MPLAB SIM), apañar el tema de las interrupciones, probarlo en el Proteus (Isis), y montar cuidadosamente todas las conexiones en la placa de prototipos, no funcionaba. Y del software no podía ser, ni de la configuración del PIC.
Metí el polímetro y vi unos valores raros de entrada / salida en las patas TX y RX, así que pensé que el problema era del MAX233. Poco después descubrí con horror que no era eso, gracias al olfato. Había cometido uno de los peores errores: había confundido Vdd y Vss en el PIC (le había invertido el voltaje). Afortunadamente son duros y tienen diodos protectores, no se que les hace la gente esa que dice que se los carga. En cualquier caso, una vez subsanado funcionó todo perfectamente.
La única secuela ha sido esta:
Del calor de la corriente disipada se ha fundido un poco el plástico de la placa de prototipos, ese era el olor que detecté.
Por si alguien quiere hacer cosas con la electrónica, os daré unos consejos:
Hace tiempo, navegando por Internet, vi una Web en la que hacían un medidor de radioactividad casero muy simple, usando una cámara iónica de fabricación casera y un transistor Darlington. Me apunté el esquema.
Hoy decidí hacer algo parecido.
Lo primero fue el detector. Como llevo MESES esperando a tener un bote de metal decente, he decidido no esperar más y hacerlo con la carcasa de un condensador electrolítico gordo, debidamente vaciado. No fue fácil; es difícil vaciarlo, la soldadura no agarra y encima el plástico derretido ese de pistola funde antes que el estaño. Menudo show. En cualquier caso, no es más que un bote con un electrodo (cacho alambre) dentro, y cubierto con albal para que quede cerrado. El propio aire será el gas a ionizar (CO2, neón o algo así hubiese sido mejor, pero pasando).
Por supuesto es un sensor pequeño, comparado con uno hecho con un bote. Al haber menor distancia y volumen, el aire se ionizará antes y el sensor será mucho más sensible (demasiado, como veremos).
En el circuito, al no encontrarse por estas latitudes el MPSW45A, le he puesto un BC517, que amplifica 30.000 en vez de 25.000. Y por si fuera poco, la resistencia interna de mi multímetro cutrillo no es 10MOhm, sino bastante menor, no la pone ni en el manual (sospecho que es 1KOhm).
Al ponerlo en marcha, alcanzaba su valor (se estabilizaba) rápido, pero parecía que a la mínima oscilaba demasiado sin venir a cuento. Creía que sufría de histéresis del transitorio de encendido el Darlington por la construcción del sensor...
...Y me equivoqué. Lo dejé puesto mientras chateaba, y al girar la cabeza vi que estaba quieto. Así un buen rato. Al levantarme se movió. Entonces entendí; me quedé quieto y él también. Y al moverme, volvió a cambiar.
Estaba detectando la perturbación de mi campo eléctrico en la habitación. La polla. No quiero imaginarme que lecturas dará esto con una muestra radioactiva de verdad. Por supuesto, puedo cambiar de escala y/o cambiar las resistencias, pero esto me ha llegado.
Querido diario:
[...]
Por fín me llegó ese programador de PICs desde Argentina, que es el lugar donde se marchó la madre de Marco para no verle nunca más. Menudo coñazo de niño y de serie; sin embargo la de Heidi, que no era mucho mejor, me la vi casi entera.
Un bonito sobre marrón, con un sello automático por valor de 15,75$ el envío... Si me costó 21€... ya se sabe el resto. Dentro del sobre, otro sobre protector acolchado, y dentro de este último, por fín, un plástico con el grabador y un CD de regalo en su fundita rígida que ya miraré mañana.
A la vuelta de la cena, sobre las 22:15, empiezo a jugar; pruebo a leer el 16F84A que tenía preparado; todo 0, perfecto. Es hora de hacer un programa.
Con el manual en pdf de ese modelo para mirar como es su ensamblador y el IDE de MicroChip, escribo esto:
;Esto es una prueba para el puto pic 16F84A
list p=16f84a
include <p16f84a.inc>
ContadorP equ 0x20
ContadorG equ 0x21
org 0x00
goto Inicio
org 0x04
retfie
PausaPeque:
clrf ContadorP
BucleP:
decfsz ContadorP, F
goto BucleP
return
PausaGrande:
movlw 0x82
movwf ContadorG
BucleG:
call PausaPeque
decfsz ContadorG, F
goto BucleG
return
Inicio:
bsf STATUS, RP0
clrf TRISB
movlw B'01010101'
bcf STATUS, RP0
movwf PORTB
Bucle:
call PausaGrande
movlw 0xFF
xorwf PORTB, F
goto Bucle
END
Al principio no me ensambla, porque puse una directiva res en una sección udata. No genero código objeto y el ensamblador es un poco tocahuevos, así que lo cambio por equ, y compila a la primera. El debugger integrado es simple, pero eficiente, y compruebo que el programa funciona perfectamente en el emulador. ¡Es hora de grabarlo en el PIC!
Ahora toca construir el circuito. Descubro que no tengo resistencias de 330 ni de 220 Ohmnios para el LED. En fin... uso una de 470, porque por debajo lo más cercano que tengo es de 68. Estabilizo el cristal de 4 Mhz con dos condensadores cerámicos de 22 pF (no tengo de 27, y para esto da igual), alimento por VDD y MCLR, pongo masas y el LED.
También funciona a la primera. Justo a tiempo, son las 23:05, hay que sacar al perro.
[...]
Es tarde, pasan de la una y cuarto. Subo este post y el video, me despido de Z, y me voy a dormir. Mañana subiré alguna foto del monigote siniestro de masilla epóxica. Pero ahora toca soñar con Nu.
Adiós, querido diario. Hasta mañana.
Volvamos atrás unos cuantos años. Uno podía encontrarse con un montón de plataformas distintas; CPCs, PCWs, Spectrums, Commodores, MSXs y algunos otros casi desconocidos por estas latitudes, como los BBC Micro, Apple II, Altair, IMSAI 8080, …
Un gran número de plataformas, sí. Cada una diferente de la otra, sí. Con sus características incompatibles, sí. Cada una con una versión de BASIC (o algo peor) distinta, sí.
Como no tenían demasiada potencia, el portar un juego a varias plataformas era un trabajo de chinos, pues se debía optimizar para cada plataforma, y eso lo sabían los Programadores (sí, con mayúsculas). Pero también es cierto que para ciertas aplicaciones no hacía falta más que un modo de texto, o con gráficos llamados desde de una interfaz común. ¿Por qué no hacer algo común para todos?
Y así fue como que en medio de ese caos surgió el CP/M. Un sistema operativo para gobernarlos a todos, un sistema operativo para encontrarlos, un sistema operativo para atraerlos a todos y atarlos en las tinieblas.
Los únicos requisitos: 80 columnas (o apaño equivalente), unidad de disco (idem) y tener un Z80 (8080) para ejecutar código. Commodore creó el Commodore 128 con un Z80 como coprocesador sólo para poder ejecutar el CP/M, y de igual manera se crearon extensiones para el Apple II y similares que tenían arquitectura Motorola (650x). Incluso el Spectrum +3, con unidad de disco, tuvo su versión.
Un mismo programa, una vez optimizado se ejecutaba en todos los ordenadores. Pues todos tenían el mismo sistema operativo, el mismo formato de ejecutable y un procesador compatible. Y todos se regocijaron.
Además, traía el Mallard BASIC, que era un intérprete de BASIC igual para todo el mundo. Un gran adelanto, sin duda. Aplicaciones como WordStar o dBase surgieron para CP/M. Hubo incluso compiladores de Pascal de Borland. Después todos ellos se portaron a DOS, pero eso es otra historia.
El fin de los 8 bits fue rápido y silencioso.
Hoy en día la situación es justo la inversa. Se tiende a una sola plataforma, el PC (bastante chapucera, el contar sus miserias se merece otro post). Sin embargo, nos encontramos que hay una infinitud de sistemas operativos.
Desde la humilde familia DOS (basado en CP/M) y sus variantes, la familia Windows y OS/2, la infinitud de distribuciones de Linux y núcleos BSD hasta cosas más exóticas como TriOS, DragonFly BSD, ReactOS, Plan 9, MenuetOS, y antiguallas como Xenix, Amiga OS o HP-UX. Incluso ahora se tiene el Mac OS, pues la arquitectura PPC ha caído (impío Apple despiadado; adios 6502, adios 680x0, adios PPC, ...). Aunque que se usen, el Windows, Linux (y sus 12.000 manejadores de ventanas incompatibles entre sí), Mac OS, FreeBSD / OpenBSD y poco más.
Una sola plataforma, multitud de sistemas operativos, multitud al cuadrado por lo tanto de formatos binarios y linkados dinámicos cuando el hardware que subyace es el mismo. Hacer hoy en día un programa realmente portable implica que ha de ser intrínsecamente lento. Por las tremendas capas de emulación necesarias para proporcionar un entorno lo más abstracto posible (y la gran cantidad de recursos que consumen), por el mínimo común múltiplo de los puntos fuertes de cada sistema operativo y por el máximo común divisor de los débiles. Es independiente de lo que optimice el compilador.
Tener competencia en el hardware haría bajar los precios del mismo (sobre todo en marcas), lo que beneficia a los usuarios. El que haya un sólo sistema operativo hace no sólo que todo esté más optimizado, sino más accesible, pues se da el caso actualmente de aplicaciones y juegos existentes para algunos siestemas operativos y no para otros. Esta unicidad también beneficiaría al usuario.
Dejando eso a un lado, lo peor es el desarrollo. Donde antes había un Programador, ahora hay 10 infraseres que no valen apenas 1/10 del Programador y les cuestan a la empresa 1/10 del mismo (¡en conjunto!); o aunque no sean infraseres, se les obliga a serlo, quitándoles el diseño, la iniciativa y el sueldo. Y se autoengañan creyendo que metiendo más gente se desarrollará mejor y antes. Es como pretender ganar una carrera a un coche de fórmula 1 con un Smart, y al ver que no se puede, poner más Smarts a correr; al final se consigue, pero trivialmente porque hay tantos coches en el circuito que ninguno puede moverse.
Knuth se quejaba del gran daño que produjo el BASIC a los futuros programadores. Yo creo que es más profundo, que el arte de programar se jodió en cuanto se convirtió en un puto marketing, como todo.
Hoy cambiaré mi sesión de Prukogi por otro mantra igualmente poderoso, del maestro Nicklaus Wirth: “Software gets slower faster than hardware gets faster”. Repeat with me, please...
Qué gran verdad. Y qué triste.
Hoy, queridos niños, vamos a ver en clase de plástica como hacer un foco de luz infrarroja. ¡Biiiieeeeen!
Usaremos para ellos unos LEDs infrarrojos (940nm), debido a que son monocromáticos, eficientes, baratos, de bajo consumo, larga duración y casi nulo calentamiento. Los alimentaremos con unos 20mA ~ 1,2V a una tensión de fuente de 5V, así podremos enchufarlos por dentro de la fuente del ordenador, un puerto USB o casi cualquier dispositivo que tenga niveles TTL.
Bajo 5V podemos poner 3 seguidos, y nos queda 5 - (3 x 1,2)=1,4V. Bajo 20mA tenemos que poner una resistencia de 1,4 / 0,02=70Ohm. Pondremos una de 68, que es la más cercana. 0,02 x 1,4=0,028W, y eso es menor que el 1/4 de vatio de una resistencia química normal, así que nos vale. Cada fila nos consume 0,02 x 5 = 0,1W; como usaremos 3 filas (3x3 LEDs), tendremos 3 x 0,1=0,3W. Teniendo en cuenta la cantidad de luz que da, es un lujo.
Como me aburría, le hice estos gráficos en Corel:
Estos son los elementos que usaremos. Aquí podemos ver un LED visto de frente y de lado, y una resistencia de 68 Ohm. Azul, gris y negro son sus colores, con banda de oro (5% de precisión). Las resistencias no tienen polaridad, lógicamente, pero los LEDs, al ser diodos, sí. En el primer dibujo tenemos el ánodo (pata +) a la izquierda y el cátodo (pata -) a la derecha. El ánodo normalmente es más largo que el cátodo, tanto en LEDs como condensadores electrolíticos y demás componentes polarizados de 2 patas. |
|
Como nos interesa que nuestra matriz de LEDs sea lo más compacta posible, soldaremos todo entre sí. Empezaremos doblando las patas de los LEDs tal que así. |
|
Soldamos y recortamos los componentes de cada fila, tantas veces como filas queramos hacer. En este caso lo haremos con 3, como se verá en el siguiente dibujo, para que nos quede un foco de 3x3 LEDs. Cada fila montada queda como el dibujo de aquí al lado. |
|
Ahora vemos de lado las 3 filas puestas en idem. Soldamos por un lado todos los cátodos, de tal manera que sólo quede el del medio (por ejemplo). | |
Y lo mismo con los ánodos, eso sí, después de la resistencia. Alimentando el sistema por las dos patitas que nos quedan, la matriz 3x3 completa luce que da gusto en IR. |
Para terminar, podemos hacer un cucurucho de cartulina forrada con papel albal y meter dentro nuestro foquito, para aprovechar mejor la luz que se emite. Aquí vienen algunas fotillos, no es plan de que ocupen sitio en la galería.
En el próximo episodio veremos como hacer chorradas con PICs. ¡Adios, amiguitos!
Se ha vuelto demasiado simple (será por el IDA, que es la caña para código muerto). No mencionaré el Cube Media Player porque hablé de él hace poco en su propio post.
Así que diré que hace algún tiempo encontré en The Underdogs el Knight Time. Es un juego antiguo y raro, de Titus. Uno de los dos primeros juegos para PC que tuve y el primero con gráficos decentes (aunque mi ordenador era XT tenía SVGA).
El juego eran dos discos de 5 1/4; por lo incómodo de cambiar entre ellos y de su propio tamaño, puse ambos en uno de 3 1/2, pero como estaba protegido siempre miraban al principio en la unidad de 5 1/4 para buscar la protección.
Por aquel entonces no fui capaz de desprotegerlo. Usaba trucos como desviar las interrupciones 1 y 3 y las usaba para sus propias rutinas, con lo que no había nada que hacer con el Debug o el D86 (que nadie diga nada del Soft-Ice, eso es para 386 mínimo). Tampoco funcionaban los desprotectores de la época, sería que tenía una versión distinta, en cualquier caso era la que estaba en Underdogs.
Con más años de experiencia, mejores herramientas y un morbo rozando lo frikiesco (o un frikismo rozando lo morboso, según se mire) lo abrí. Y fue relativamente simple, pues una vez hacía todas las comprobaciones de protección la decisión de si había o no protección se tomaba en un solo punto. Cambié el salto condicional y funcionó, menos de 15 minutos. Además determiné que estaba programado con un compilador de C raro (ni MSC ni TC o BC) con rutinas en Asm. Localicé las de teclado, gráficas, joystick, etc.
Otro ejemplo, el Marranos en Guerra, juego antiguo que no instala en núcleos de NT, pero que me gusta; después de engañar al instalador para que lo instalase en XP el juego funciona, pero al salir inutiliza el teclado y el ratón en las ventanas que hubiese abiertas antes que él, incluyendo el escritorio.
Menos de dos minutos (el record hasta ahora): veo en importaciones EnableWindow y EnumerateWindows, hago referencias cruzadas y veo que desde la misma función, la cual se encarga de quitar o devolver input a todas las ventanas menos ella misma (supongo que para no molestar, pues casca el juego si sale de pantalla completa). Parcheo el salto condicional de esa función para minimizar los cambios (sólo cambian 6 bits en un byte) y el juego va perfecto. Se ve que al final no la llama por alguna razón (casque silencioso).
El último ha sido un juego de DOS que adquirí hace poco en su versión registrada y que me encantaba de crío, el Moraff’s World. Volví a jugar a él y todo iba bien, hasta que fui a enfrentarme con el enemigo especial del nivel 16. No aparecía por ninguna parte, y en el mapa me decía que fuera al este cuando estaba ya en el borde este de la mazmorra.
Este caso fue bastante más complejo, pues he estado dos días con el IDA. He localizado como va todo el tema gráfico, la magia, la forma de las estructuras de datos usadas en el programa, los enemigos, el mapa,... hasta que al final he visto como es el formato de los juegos grabados, a imagen y semejanza de las estructuras en memoria.
Así que en el juego grabado en ese nivel, archivo 40.dun (4 por el personaje, 0 porque es el nivel por defecto; los 1-7 son las mazmorras en sí mismas, 32 niveles por cada uno), y saltando los 3 primeros bytes se encuentran los descriptores de enemigos de ese nivel, 6 bytes por cada uno, siendo el primero el del enemigo que buscaba, ese Shadow Dragon King. Y en efecto, el primer byte, la coordenada X era 88 cuando la mazmorra tenía 78 como máximo; parcheé a 76, y al cargar estaba a dos casillas al oeste de mí, así que pude enfrentarme, vencerle y obtener la bonificación +25 para mi Long Sword.
Además descubrí analizando todo el juego ¡que se pueden hacer trampas! Si se pulsa Alt.gr. + 1 te da 10 de vida por la patilla, si lo dejas pulsado no para de subir, aun por encima de la vida máxima del personaje.
¡Atención! Este post contiene material de teoría de compiladores explícito. Si no se considera preparado, no lo lea (o sí, y suelte algunas de estas frases en sus reuniones de amigos y quede como un... friki).
Hoy voy a hablar del lenguaje ese que inventé y el cual tengo a medio implementar.
Lo primero que tengo que decir es que el código está organizado lógicamente en espacios de nombres anidados. El código fuente viene en archivos, los cuales no tienen necesariamente una correspondencia con esos espacios de nombres. Cada módulo puede tener varios (obligatoriamente debe contener al menos uno), y un mismo módulo puede estar definido en varios archivos (basta con usar el mismo nombre del espacio de nombres, el contenido se mezcla).
El compilador incluye también un intérprete pues, bajo ciertas condiciones, una función puede ser marcada para ser ejecutada en tiempo de compilación, y de esa manera generar código para ser compilado utilizando la potencia expresiva del propio lenguaje, y haciendo obsoleto el concepto de procesador de macros.
Cualquier convención de llamada de funciones, uso de registros, inclusión inline, y en general directivas de compilación no se pondrán como pragmas de preprocesadores, casos especiales de comentarios o palabras reservadas del lenguaje. Sencillamente serán etiquetas con valores dentro del propio código, como si las propias funciones fueran objetos en un lenguaje de objetos sin herencia.
El lenguaje es en sí mismo imperativo, pero con notación funcional y considerando como funciones todos los elementos sintácticos (lo cual es MUY útil en el caso de los IF para el tema de asignaciones). Permite anidar funciones, y tiene orientación a objetos con herencia simple e interfaces (ortogonales entre sí, claro). El nivel semántico queda definido por el sangrado (libre) del código, así no se necesitan delimitadores sintácticos a la { } o palabras reservadas del tipo Begin - End.
Tiene un sistema de tipos estricto y fuerte, con
La sintaxis a nivel externo es muy simple y matemática:
NameSpace Fulanito
Suma: Integer * Integer -> Integer
Suma(x, y)=
Resultado: Integer
Resultado = x + y
Return Resultado
Por ejemplo; para desambiguar una variable que contenga una función de una declaración de función, hacemos un tipo único agrupado: (Integer * Integer -> Integer) en vez de la declaración de Suma. De igual manera, (Integer * Integer) -> Integer nos define una función que sólo tiene un parámetro, una tupla de dos valores enteros.
La compilación se hace en dos pasadas, pues se pueden usar variables y funciones definidas fuera de orden; el compilador mantiene todo en su base de datos de memoria, eliminando la necesidad de código objeto. Las librerías estáticas se enlazan en su forma de código intermedio, para así poder aplicar optimizaciones avanzadas al programa en conjunto (y de nuevo, no requerir código objeto propiamente dicho, sino una base de datos de espacios de nombres nativa al compilador).
De acuerdo, esto usa bastante memoria y enlentece el compilado, pero genera aplicaciones mucho más eficientes.
Finalmente, después de hacer las optimizaciones buenas, se traduce a la plataforma y se hacen las típicas optimizaciones de registros y mirilla típicas de la plataforma y a correr.
Si alguien ha entendido algo, ¿algún comentario?
Hace algún tiempo, el cuñado de mi jefe se fue de viaje a China. Y de allí trajo unos “iPods de 8 GB, que no los han sacado todavía aquí, y muy baratos”. En este caso no hablamos de un tocomocho sino de una estampita, los chinos le engañaron como idems.
Quizás de frente pueda engañar, si obviamos los mandos cutrillos, la inscripción de arriba y el material que se pringa con mirarlo. Por detrás, a pesar de tener serigrafiado el logo de Apple, tiene graves fallos ortográficos, literalmente: “Designsd by Appls in Callfomia Asssmbisd in China”. El manual de instrucciones es peor, no sólo ha pasado por un cutretranslator peor que el de la AltraSound, sino que ha sido OCReado (si no, no me explico estas faltas y errores).
El CD de drivers es un CDr, pone “MP4 driver” y… ¡está virgen! (como a mi me gustan). Unos cascos Cutres con C mayúscula y una caja con la inscripción “MP4” (nada de Apple) con una foto de otro reproductor blanco completan tan maravilloso pack.
¿Cómo es que lo tengo yo? Compró varios, al módico precio de 70€ cada uno, y uno de ellos fue para las hijas de mi jefe. Aparte de que saltó un virus en cuanto se enchufó el cable USB, al meter canciones se les “multiplicaban”. Lo cual es normal: estaba trampeado para parecer de 8 GB, pero en realidad es bastante menor. Al formatear va bien, pero el sistema de archivos se sobrescribe cíclicamente en cuanto se meten cosas. La corrupción está asegurada. Como mi jefe iba a tirarlo, le dije que me lo diese para aprovechar la pantalla (128x128x65K).
En efecto, es una falsificación total. El cacharro dice que su FW es SC85051f, ACT_V3.5.25. He mirado por Internet y hay gente a la que también se los han vendido como un modelo de Sony. Por el USB el FW se identifica como 3.5.37, y nos da la primera pista: Wilson Co. Ltd. Por dentro, el chip de memoria es de 128 MB (se puede sustituir directamente por uno de hasta 2 GB, aunque es de montaje y con patillas pequeñas). El FW estaba modificado para mostrar un logo mal hecho del iPod al arrancar, y tenía quitada la opción de radio FM (lógico, pues no tiene ese chip aunque sí todos los de soporte; viene en DIP, sería fácil de ponérselo).
Estos nuevos reproductores “MP4” son cacharritos de bajo coste y muchas prestaciones muy comunes en china, hasta tienen un estándar conocido como S1MP3 para reproductores de música, y MP4 para los de nueva generación (videos en AMV, fotos JPG, etc).
El cerebro de todo esto es un ATJ2085P. Es un chip que tiene su DSP de 24 bits, su DMA, sus puertos IO… y un núcleo de Z80 a 60Mhz. Un Z80 a 60Mhz (el del Spectrum va a 3,5 cuando la ULA lo permite), con 128 MB de memoria y una pantalla 128x128x65K. ¡Diox, es como para correrse de gusto!
Después de un susto pequeño con un firmware y de otro grande con otro, lo tengo como debía ser original, aunque sin chip de radio. Posiblemente se lo ponga. Lo de la flash de 2 GB lo pensaré, porque no es fácil.
Aunque sea un timo de lo peor, estoy enamorado de la maquinita. Tiene de casi todo (MP3, WMA, WAV, ACT, AMV, MTV, JPEG, GIF, graba audio, tiene agenda, trae juegos, vale de disco, tiene sistema de protección / encriptado…) y además puedo hacer mis programas y flashearlos. ¡La caña de Españ… de China! Dejaré un par de fotos en la galería.
...Y otra versión del blog.
La mayor parte de los cambios son en la interfaz de administración, y en la BBDD. Aunque algunos se ven por fuera, como la desaparición del "Acerca de", renombrado de cosas, sección nueva en obras, etc.
En honor al editor de texto para descargas:
El post prometido (a mi mismo, no creo que le interese a nadie por su ininteligibilidad).
Meditando sobre la etapa de preprocesado de un compilador, tuve una revelación. ¿Y si el lenguaje del preprocesador fuese EL MISMO que el lenguaje preprocesado en si mismo? Sería como el caso de tener JScript en ASP generando JScript para HTML.
Pero seguía estando el tema del mezclado de ambos en el mismo fichero… y se encendió otra bombillita: hace tiempo pensé en poner las directivas personalizadas para cada función en el lenguaje, a modo de “etiquetas”. Podemos poner una para la ejecución en tiempo de compilado.
Juntando eso con la notación funcional – matemática, con la gramática extendida para tener operadores definibles (y su analizador híbrido), con el lenguaje que hice funcional imitando a imperativo y cuatro cosas más, la revelación ha sido completa.
Hasta he pensado el tema de interfaz con (linkado contra) otros lenguajes, y su extensión de clases (pues tiene tipos simples correspondientes al hardware que subyace), con herencia simple e interfaces, y la sintaxis de todo.
Todo encaja. Tengo el lenguaje que buscaba. Que pena tener tan poco tiempo.
A ver, algo que me han pedido. Vamos a ver como piratear un programa. En este caso se trata del Cube Media Player, v2.05.0117.
Echando un vistazo por encima con un editor hexa (uso UltraEdit32, que vale para todo) vemos que es un exe sin empaquetar ni proteger. Perfecto, derechito al IDA Pro.
Se tira su ratito pensando y lo analiza bien. Veamos las cadenas... en 004725E8 hay una cadena "Software\CubeMediaPlayer", típica de acceso a registro. Pinchamos, le damos a la X (referencias cruzadas) y vemos que se le llama desde tres procedimientos, igual que las cadenas "User Name" y "Register Code" que están por encima. Sospechoso.
El primer procedimiento se dedica a leer del registro y guardarlo en un buffer. No es gran cosa. El último hace lo contrario, lo devuelve al registro junto con las preferencias del usuario. Tampoco gran cosa. Ahí identificamos el nombre y la clave (en 0047C760 y 0195FE30 respectivamente).
El del medio (de los chichos) es distinto. Hace un montón de cuentas y al final entra en un bucle de comprobaciones, y sale o bien con un 0 o con un 1 (caso bueno) en EAX. *MUY SOSPECHOSO*. Para hacer la prueba, relleno desde 0040CD9E hasta 0040CDA5 con 0x90 (NOPs). Bingo, está registrado.
Hmmmm quizás haya sido un mal ejemplo, ha sido muy sencillo. :/
Nota: Todo son direcciones de memoria, no offsets de fichero (obviamente). Lo digo porque alguien es muy brutito...
Llevo mucho tiempo sin visitas, como al principio... mola escribir cosas así, porque puedes escribir de lo que quieras sin pensar en nadie.
Centrémonos. Todavía recuerdo cuando aprendí Pascal en un PCW. Es un lenguaje que siempre me gustó. Sistema de tipos estricto, sintaxis limpia.
Así pues, hoy en día mi lenguaje por definición es el Delphi, que es un dialecto muy ampliado de Pascal con clases, esteroides y un IDE digno.
Viendo lo que ha sacado Borland (o DevCo, o como coño vaya a llamarse ahora esa parte de Borland), en TurboExplorer, me ha dado un yuyu. Y ese yuyu me ha hecho bajarme... ¡el Lazarus!.
¿Qué decir? Con la edad me he amariconado. En los tiempos del DOS habría vendido mi alma al diablo por un IDE así, pero teniendo el BDS 2006 sólo he podido pensar tres palabras: juguete, incómodo, feo. Bueno, también he pensado "palaustre" y "prukogi", pero no tienen nada que ver con esto (creo).
Es aparentemente como un Delphi 5 cutrosillo, y con menos controles. Se hechan de menos a los poderosos Indy. Ya lo probaré a fondo y os comentaré, pero de momento he decidido compilar la ventana por defecto, según se abre: ¡6 MB y pico! Aunque después del susto he visto que la mayoría era información de depuración, y pasando un strip se queda en mega y medio (aún así más que el Delphi 2006, con el último VCL). ¿Qué pasó con el SmartLink ese?
Pero soy raro, y hasta un poco masoca, así que voy a dedicarle algún tiempo. Tengo que probar las extensiones al lenguaje del FPC, ese modo OBJFPC de moda.
Ya no hace falta ir a "Archivo" para mirar los posts antiguos (y encima uno a uno); acabo de ponerle unas opciones de navegación al final de la página para ir de 10 en 10 adelante y atrás, además de ir al principio y fin.
No, no ha sido nada trivial, y menos porque el mandato LIMIT para SQL no es estándar, y ni Access ni SQL Server lo admiten.
Si es que os quejáis de vicio...
Ayer estuve haciendo limpia entre todos los proyectos de Delphi que tengo empezados. La mitad de ellos eran analizadores sintácticos / semánticos y traductores en general; para Freud tendría algún significado.
¿Cómo debería ser el lenguaje ideal? No hay lenguaje ideal. Cada elección de diseño aporta ventajas e inconvenientes a partes iguales.
Un lenguaje interpretado es ideal para la depuración, para construcciones dinámicas y de alto nivel y para su integración en entornos cualesquiera. Pero al ser tan dinámico es bastante más lento que uno compilado, el cual ya tiene resueltos estáticamente los enlaces y traducción, y ha podido ser optimizado profundamente, amén de no requerir un entorno para integrarse con otros lenguajes.
Con los paradigmas es casi peor, porque aunque los lenguajes y la forma de programar en ellos sea radicalmente distinta, todos sirven para todo. Es un tema de comodidad, depende para lo que se lo vaya a usar.
Y luego está el tema del traductor, mi preferido. Un lenguaje como Pascal o C puede implementarse con LR (SLR, LALR) sin problemas, en el caso del Pascal basta con un LL un poco modificado (al fin y al cabo, el Pascal fue diseñado para compilar en un solo paso, sólo hay que desambiguar el IF).
Sin embargo, si quisiese un lenguaje compilado que pudiese definir sus propios operadores (no sobrecargar los existentes) teniendo en cuenta la asociatividad y precedencia de éstos no nos valdría un LR a secas, por usar tablas estáticas, con lo que no nos valdrían ninguno de los generadores automáticos que hay (mi solución a esto fue usar una técnica híbrida, con un LL modificado para toda la gramática que no fuesen expresiones y precedencia de operadores por funciones de precedencia para éstas, aunque esto es otra historia).
Me está quedando un post muy largo y no he entrado en detalles de ningún tipo. Divago. ¿Cómo debería ser un buen lenguaje para desarrollar aplicaciones eficientes tanto en tiempo de ejecución como de desarrollo? Aunque quizás de lo segundo, puede encargarse un entorno de desarrollo integrado, fijaos si no en el VB.
Por mi parte: compilado, imperativo / funcional, con macro-preprocesador, capacidad de inline, un sistema de tipos fuerte aunque con amoldamientos y una sintaxis clara y ortogonal. Y si tiene objetos (en algún sentido), herencia simple con interfaces añadidos.
¡Tenemos nueva chorrada!
A petición popular (?), vuelve la sección de frases célebres aleatorias.
Disfrutadla.
P(t): Van 20 post ya .
¡Ya tenemos sección de descargas!
Y como lo prometido es deuda, ahí va ese programa para poder ver y exportar las imágenes del Print Master y News Master, junto con varias bibliotecas.
Si queréis que ponga algo en descargas de interés general para todos los visitantes de este blog, se admiten sugerencias.
Todavía sigue estando un poco verde el tema, ya lo iré apañando poco a poco.
Hace muuucho, mucho tiempo, al poco de tener mi primer PC (eso fue en 7º / 8º), me pasaron un programita... se llamaba Print Master y era una especie de asistente de publicaciones, como el publisher pero cutroso y en DOS / CGA. Traía su librería de cliparts (blanco y negro, por supuesto). Me encantó al instante. Además, podía hacer mis propios dibujos en una librería de usuario.
Tiempo después, me pasaron el News Master. Este además de tener asistentes, te dejaba trabajar WYSIWYG sobre la hoja, mejoraba la resolución de pantalla (pues admitía EGA y tal), y te dejaba cargar varias librerías de cliparts, siendo compatible además con las del Print Master.
Sigo sin saber porqué, pero tenía que tener acceso a esas bibliotecas. Así que por ingeniería inversa saqué el formato, y me he hecho un programita visor. Además, pude sacar también el formato de los dibujos de los bordes del Print Master, cosa que el News Master no hacía, benditas hormiguitas.
No se si habrá otro friki nostálgico por ahí, así que si alguien quiere conocer el formato, sólo tiene que decírmelo. Cuando tenga operativa la sección "Descargas", pondré el programita junto con todas las librerías que tengo. Si alguien tuviese alguna más, le agradecería que me la mandase.
Yo también he caído. Ayer cogí mi vieja cámara web, la abrí, le retiré el filtro de infrarrojos y en su lugar puse dos trocitos de negativo fotográfico velado (opaco en visible, pero transparente en infrarrojo), y me he construído mi cámara de infrarrojos.
Jugando con ella he podido observar las típicas marcas de agua (ausencia de tintes) en billetes, sello de autenticidad de MicroSoft, etc, pero además he observado otras cosas que no comentan en las otras webs.
Los ojos... que bonitos me quedan esos ojos claros y antinaturales. Por contra, me muestra más barba de la que tengo y marca las venas que es un primor (son más penetrantes estos rayos). Aparentemente, la materia orgánica los refleja muy bien, ya sea madera o tortilla de patatas; y por contra, no hay imagen en un televisor o monitor encendido, sea tubo o LCD, ni tampoco en las pantallitas LCD de relojes. Los LED tampoco se ven iluminados, lo cual demuestra lo monocromáticos y eficientes que son. Salvo obviamente los de los mandos a distancia, que sirven perfectamente para iluminar el ambiente.
Puedo leer la página de un libro sin haber pasado la anterior, delatan el pelo teñido de mi madre (vaya shock, completamente blanco; aunque es posible que sea porque el tinte sea invisible en infrarrojos, lo investigaré) y muestra bastante de lo que hay por debajo de la ropa ceñida (sin comentarios; y no, Abj, no te voy a hacer una cámara de estas para tí... gratis). Por supuesto, un Carbon CD de esos se ve especular, como un CD normal. Y algo espectacular: no se ve la tinta azul de bolígrafos y plumas (ni la mayoría de tintes azules, en general; se ve el blanco de debajo, sea papel o tela, o traslúcido en el caso de plásticos), así que puedo ver los libros pinturrajeados como intactos, incluyendo palabras tachadas; con el lápiz no pasa.
Estoy como un niño con juguete nuevo, hasta me he hecho un programa para capturar y tratar las imágenes, principalmente para reducir en tiempo real el ruido infrarrojo del calor. Tengo que analizar el comportamiento de más materiales, así como hacerme un foco de luz infrarroja a base de LEDs para disfrutar de una visión nocturna decente.
Seguiré investigando...
No tengo casa propia (de momento) y ya estoy pensando como automatizaré todas las cosas cuando la tenga.
Mi idea era poner un PC, tipo barebone de diseño, como centro multimedia en el salón. Con su conexión a la TV y altavoces, su mando a distancia y su ADSL podría hacer las veces de TV, video, DVD, cadena de música, juegos, teléfono, videoconferencia, fotos, ...
Y entonces vinieron las pajas mentales: la automatización de TODO. Que ese ordenador haga además de contestador automático, BBS y fax (a través del modem de voz), que encienda y apague la calefacción, aire y luces y controle la alarma. Y por supuesto, sirva de pasarela entre todos esos dispositivos, además de internet.
Poder encender las luces via email o llamada perdida "especial" a casa, o hacer que la desactivación de la alarma llame a la policía si no enciendes y apagas la luz 3 veces seguidas en los 30 segundos posteriores. Eso es poder.
Así que después de pensar, pensé usar los cables de la luz como bus para interconectar todo; es barato, no hay que tirar cables ni hacer instalaciones, es barato, la interfaz electrónica es simple y es barato. Así que miré alguna forma fácil de hacerlo; en un principio, pensé meter muchas frecuencias, una para cada cosa, y que se filtrasen en cada receptor via un filtro paso bajo más uno paso alto (al ser de la misma frecuencia el desplazamiento de señal sería nulo; además, sólo serían dos condensadores y dos resistencias, barato).
Eso sí, habría que usar un montón de frecuencias, elegir con cuidado las frecuencias fuera de los anchos de banda de los filtros, y en general hacer una definición estática; por eso pensé en convertir el sistema en una especie de bus serie unidireccional. Así que pensé en x10.
Hay mucha información sobre el mismo, aunque para el sistema de corriente americano. Hay un documento de MicroChip (00236a) que nos dice como hacer interfaz directa a PICs que me pone a cien. Convirtiendo el tema de corriente de América a España (de 120V 60Hz a 240V 50Hz), el sistema es el mismo, con su señal a 120KHz. Por ejemplo, para la detección de fase a 0 usan una resistencia de 5MOhm, cuando aquí tendría que ponerla de 10MOhm para mantener los 33mA que necesita la linea de interrupción del PIC.
Así que hasta entonces, aquí estoy haciendo y simulando esquemas de controladores domésticos, intentando no meter picos con la conmutación. Relé o triac... he ahí el dilema.