Cuando hablé de 2M y Stacker, mced, me sugirió escribir un artículo sobre las técnicas de optimización usadas en la época de los 8 bits.
A muchos, les puede resultar hoy día increíble, pero por aquellos años 80, la máquina más popular en nuestro pais era el Sinclair ZX Spectrum 48K, un microordenador personal bastante limitado.
Su CPU Z-80 a 3,5 Mhz, tenía una potencia de cálculo algo superior a sus coetáneos. Sin embargo, no iba asistida por otro hardware, de manera que se encargaba de manejar toda la lógica, las E/S, el manejo de sprites, y la generación de sonido, lo que al cabo, implicaban una limitación.
Lo más apremienta era la memoria, que de 48 Kb. totales (en realidad eran 64 Kb, pero 16 Kb. eran de ROM), descontando la memoria de vídeo, y las areas reservadas, quedaba entorno a algo más de 41 Kb. utilizables. Este valor, era todavía inferior, si se descontaba lo que ocupaba el cargador BASIC. Si nos referimos al modelo básico, éste tenía instalados sólo 16 Kb., por lo que nos debíamos contentar con 9 Kb. disponibles.
Me gustó mucho Meteor Storm, de 1982, que metía en 7 Kb., un clon del clásico Asteroids de Atari, manteniendo gran parte de su jugabilidad intacta.
De esta manera, contábamos con esos 41 Kb. en el mejor de los casos, para meter un juego completo, incluyendo, la configuración, lógica, gráficos, efectos de sonido, música y los datos necesarios para cada uno de los niveles.
Durante este primera época, esa limitación, solamente se superaba con arquitecturas ingeniosas, y un dominio del lenguaje máquina o del ensamblador altísimo.
Quizás de todos ellos, destacaría Turbo Esprit, de 1986.
Posteriormente se empezaron a aplicar técnicas de compresión, que aunque usaban algoritmos sencillo del estilo RLE primero, y LZ después, obtenían una gran reducción del espacio de almacenamiento disponible, especialmente al tratar con gráficos, mapas, o música. El inconveniente era que necesitaban ser descomprimidos antes de ser usados, requiriendo tiempo de CPU y memoria.
Probablemente el ejemplo más relevante fuera Gremlins de 1985, una aventura basada en la película de la misma época, donde sólo el espacio necesario para almacenar todos los fondos necesarios para el juego. era casi el doble del total disponible.
Proliferaban los modelos de 128 Kb. (128, +2 y +3), que disponían de mucha más capacidad de memoria. Sin embargo ésta, y debido a las limitaciones de direccionamiento del Z-80, era básicamente el mismo 48 Kb. con 64 Kb. adicionales en otras páginas a las que se podía acceder puntualmente.
Con la nueva memoria disponible, se optó por las multicargas, que funcionaban generalmente requiriendo que el usuario cargarla los niveles extra desde la cinta cuando se necesitaban en los modelos de 48 Kb., y que estaban completamente cargados en los de 128 Kb.
Por ejemplo Operation Wolf de 1988, cargaba más de 100 Kb. de contenido, que vendrían a ser más de 15 minutos de carga. En uno de 48 Kb. la carga inicial ser reducía, pero era necesario cargar un par de minutos de datos cada vez que superábamos un nivel.
El colofón, debido a las limitaciones inherentes de un hardware ya obsoleto por aquella época, lo tenía Street Fighter II, que con sus más de 200 Kb. requería multicarga, en los modelos de 128 Kb.
Es fácil darse cuenta que cuantos más datos había que cargar, más tiempo tendría que esperar el usuario. A un ritmo medio de 1500 Kbps, si excluíamos sincronías y cabeceras, era algo determinante. Por otro lado, una piratería en aumento, y que pasaba inicialmente por los copiones (las dobles pletinas estaban al alcance de pocos), hicieron que se desarrollaran sistemas de protección y aceleración de carga.
Estas técnicas se llamaban esquemas de codificación, y si hablamos de protección pura, tendríamos los bloques sin cabecera, que también ahorraban algo de tiempo.
En cuanto a protecciones, Alcatraz, y Alcatraz 2, fueron incluidos en títulos muy populares.
Sin embargo, el más exitoso, fue Speedlock, que llegó a su versión 8, y además de proteger contra copias, aceleraba la carga hasta un 150%. Vulgarmente se les llamaba cargas Turbo. De hecho, esta aceleración, podría ser mucho mayor, pero a costa de introducir ruidos que podrían causar un error de carga.
Como ejemplo de Speedlock en sus últimas evoluciones, cabe mencionar Robocop 3 de 1992.
Me gustan estos articulos, llevo siguiendo el blog desde hace ya mucho tiempo. Pero nunca me anime a comentar. ^_^
Es impresionante el ingenio que tenian los programadores de aquella epoca para luchar con las limitaciones que tenian esas maquinas. Me fascina el nivel de optimizacion que tenian que hacer, en cambio hoy en dia da igual. Total si la espacio tenemos de sobra y la memoria no cuesta mucho.
A veces pienso, si se pusieran a optimizar bien el software, y a lo mejor trabajar a un nivel mas bajo .. obtendrian unos resultados impresionantes con las maquinas de hoy en dia.
Un saludo 😉
Llevas razón Bobby en que un software actual con las técnicas de antaño, volaría con el hardware que tenemos.
No obstante, hay que considerar que el tiempo de desarrollo que necesita un programa escrito de esa manera, es varias veces superior a las tecnologías modernas, por lo que repercutiría en el precio, y volveríamos a precios del estilo de 1000 € por una licencia de Wordperfect.
«Las dobles pletinas estaban al alcance de pocos»
Puede, Guti, pero conectar el EAR de un cassette al MIC de otro permitía obtener los mismos resultados. Y si por medio ponías el Spectrum con un mítico copión llamado Audiocopy (creo recordar), ni los juegos en turbo se resistían. Precisamente uno de mis favoritos y que nombras, Turbo Esprit, «cayó» con este método.
A veces, por otra parte, pienso que la falta de optimización del software actual también forma parte de un acuerdo tácito con los fabricantes de componentes. Un software bien diseñado no propicia la renovación del hardware. Ahí tenemos el ejemplo de Microsoft y los netbooks: en cuanto han querido, han pulido todo el código de Vista para poder hacer funcionar Seven en ellos.
Creo que tienes razón mced en lo de la falta de optimización como algo acordado con la industria del hardware. No obstante, dudo que sea un acuerdo explícito, sino algo más bien del estilo a «Desarrollo de manera rápida aunque sea poco eficiente, y además a los fabricantes de hardware, ya les va bien».
No recuerdo ningún programa que tuviera un SpeedLock 8, es más, juraría que el SpeedLock llegó hasta el 7 descontando, claro está, las versiones de la protección para los disquetes de 3 pulgadas del +3 (y supongo que del Amstrad). La verdad es que solo el tema de las protecciones de cinta daría para varias entradas en el blog porque hubo muchas y muy variadas.
Con lo que no puedo estar de acuerdo es con lo de la optimización, si me permitís la discrepancia, porque me parece una especie de simplificación por reducción al absurdo. En un procesador moderno es IMPOSIBLE escribir código correcto a mano. Mi argumentación tajante se basa en que un modesto Z80 apenas tiene una forma muy primitiva de pipeline (algo tiene) y no hay varias unidades de ejecución de enteros, coma flotante y renombrado de registros, por poner solo unos pocos ejemplos. La tarea de compilación se ha vuelto francamente compleja y uno de los objetivos de arquitecturas como RISC es, precisamente, simplificar ese trabajo todo lo posible. Recuerdo que, con la llegada del renombrado de registros, técnicas de optimización que habían funcionado desde los 8 bits, como poner a cero el registro A con XOR A en lugar de con un LD A, 0 (AX en 8086), pasaron a estar prohibidas porque suponían una pérdida de rendimiento.
Recuerdo que hace ya unos cuantos años, allá por el lejano 1997, un primitivo compilador GCC ya me enseñó como optimizar una multiplicación usando la instrucción LEA (y yo estaba intentando reescribir una función C en ASM que era crítica para ver si conseguía hacerla más rápida). Lo que hay que hacer hoy en día con procesadores de 64 bits como el i7, mejor ni me lo imagino.
Según acabo de verificar José Luis, al menos Robocop 3 iba con Speedlock 8. En cuanto a la optimización, pienso que el ensamblador en manos de un programador experto, siempre generará un código más eficiente que un compilador, siempre y cuando la arquitectura de destino esté definida.
No importa que sea un Z-80 un 68000 o un i7. Otra cosa sería un código que funcionara razonablemente bien en diferentes variantes de arquitectura, y ahí el compilador, es probable que venza.
Me ocurrió lo mismo con LEA para efectuar multiplicaciones, y con muchos otros trucos que descubría al estudiar el ensamblador generado por buenos compiladores.
Si tienes una copia de eso, me interesa. Más que nada porque la versión de WoS lleva SpeedLock 7 y la página de tzxvault, que tiene los juegos clasificados por protecciones, tampoco tiene nada en SpeedLock 8.
Sería un gran hallazgo para el mundo del Spectrum y es un tipo de protección que no he podido probar nunca en mi emulador.
Aún así, albergo dudas, ¿no sería la versión para CPC la que llevara SpeedLock 8?. Porque es raro que en ningún sitio de software para el Spectrum se haga referencia a esa versión.
Tienes razón, WOS solamente cita Speedlock 7, pero encontré la fuente que hablaba de Speedlock 8: http://newton.sunderland.ac.uk/~specfreak/Schemes/schemes.html
Sin embargo está con un interrogante, por lo que tal vez nunca llegara a lanzarse oficialmente.