Citando a Martin Korth, autor de los emuladores NO$MSX y NO$GMB, entre
otros, en ensamblador y para Windows (!): "Optimization dies. Only heros
live forever".
En cualquier caso, y antes de arrancarnos la carne de los huesos, como
programador tengo que decir que "optimizar", ya optimizan y mucho los buenos
compiladores profesionales actuales. El problema de "ineficiencia" al que os
referís, tiene que ver con un problema de arquitectura más que de
programación: hay que conseguir que un montón de elementos de hardware
completamente diferentes actúen frente al programa de un modo análogo, y
esto sólo se consigue sacrificando rendimiento máximo. Es el mismo problema
de Java, aunque se enfoque de una forma diferente.
De todas maneras, no creo que la comunidad del MSX sea la más adecuada para
criticar la falta de optimización de los programas, mientras se obstina en
programar en BASIC, lo que claramente desaprovecha las capacidades de
nuestras maquinitas. De todos modos, lo importante no es la optimización,
sino que el producto resultante sea atractivo. Los juegos de Imanok y de
MSXKun son muy buenos, tienen una calidad fantástica y un buen diseño: no
necesitan manejar la CPU al 100%. El problema es diferente: el diseño debe
primar. Y os lo está diciendo un programador...
Siguiendo con el tema de la optimización, hay que matizar algún aspecto.
Optimizar es conseguir la mejor solución posible en una variable. Por tanto,
antes de avanzar en la idea de optimización, hay que elegir qué queremos
optimizar: velocidad de ejecución, tamaño resultante del programa,
utilización de RAM... El problema radica en que en MSX no se puede ni se
debe optimizar una única componente, sino alcanzar un equilibrio entre las
tres, porque en general, tanto la memoria como la velocidad de proceso están
muy limitadas.
Aquí es cuando empiezan los problemas. Ejemplo muy básico, de andar por
casa.
Volcado de RAM a VRAM - distintas perspectivas
1.-Uso la BIOS y me despreocupo: casi no ocupa espacio, pero es MUY LENTO.
LD HL,ORIGEN_RAM
LD DE,DESTINO_VRAM
LD BC,NUM_BYTES
CALL LDIRVM
En total, esto ocupa unos 12 bytes y funciona bien. Pero te permite copiar
muy pocos datos por interrupción, lo que puede resultar grave para
desarrollar un juego con una fuerte carga gráfica (digamos, con scroll).
2.-Reprogramo la BIOS y consigo algo que funciona mejor y puede ser un poco
más rápido.
LD HL,ORIGEN_RAM
LD DE,DESTINO_VRAM
LD BC,NUM_BYTES
CALL MI_RUTINA_1
MI_RUTINA_1:
; Y esto no está muy optimizado, lo estoy programando "para que funcione"
; Hacemos que el puntero a VRAM del VDP esté donde queremos
DI
LD A,E
OUT [99h],A
LD A,D
OR 40h
OUT [99h],A
; Hacemos algún apaño
LD E,C
LD C,98h
; Empezamos el proceso de copia
BUCLE:
OTIR ; Copia datos
DEC E
JR NZ,BUCLE
; Y ya está
EI
RET
Es labor del programador saber cuándo se pueden mandar datos a la VRAM.
Recomiendo hacerlo después de la interrupción de V-BLANK, que es cuando más
"traga" la VRAM. Es decir, cuando tiene un mayor ancho de banda disponible.
NOTA: quizás se me haya colado algún error, porque estoy escribiendo esto de
memoria. Si está mal, que alguien me corrija, por favor. WYZ?
3.-Sólo apto para freaks: rutina de copia super-rápida para psicópatas y
demosceners.
El truco está en que la instrucción OTIR es MUY LENTA y hace muchas
comparaciones que son innecesarias. Crearemos una nueva versión, más rígida,
que ocupa mucha más memoria, pero que se acerca mucho más al límite teórico
de transferencia:
RUTINA_RAPIDA:
; Parámetros: HL- origen de datos en RAM
DE - destino de datos en
C - número de bloques de 256 bytes a copiar
; Vamos allá. El principio es idéntico
DI
LD A,E
OUT [99h],A
LD A,D
OR 40h
OUT [99h],A
; Hacemos algún apaño
LD E,C
LD C,98h
; Empezamos el proceso de copia
BUCLE:
OUTI
OUTI
OUTI
..... (habría que repetir esta misma instrucción 256 veces seguidas!)
DEC E
JR NZ,BUCLE
; Ya está
EI
RET
Bueno, aparte de perder flexibilidad, puesto que aquí copiamos en bloques de
256 bytes como mínimo, lo cierto es que esta rutina es mucho más rápida,
puesto que OUTI tarda únicamente 4 ciclos por dato.
Siendo un tanto optimista, podríamos copiar con una rutina como ésta
bastantes datos. Aun así, nunca os recomendaría (por pura prudencia) copiar
más de 1 KB o de 1,5 KB por interrupción, puesto que hay que tener en cuenta
que a 60 Hz las cosas son más difíciles que a 50 Hz, es decir, no se dispone
de menos tiempo de v-blank y, por tanto, se pueden copiar menos datos. Para
psicópatas en activo a los que no les preocupe trabajar SIEMPRE a 50 Hz,
imagino que se podrían alcanzar los 2 KB, aunque raspando.
Como comprenderéis, esta rutina es adaptable para que, siendo bastante
rápida, soporte tamaños menores y ocupe menos espacio de programa. Por
ejemplo, repetir 32 veces la instrucción OUTI en lugar de 256 puede ser un
equilibrio razonable entre velocidad y tamaño de programa.
Vaya, menudo sermón os acabo de endosar. Espero que no me lo tengáis en
cuenta. Si a alguno de los editores de revistas les interesa, pueden
publicar este mini-artículo, o rogarme/pagarme/comprarme para que haga uno
un poco más extenso y con más detalles al respecto.
A todos, un saludo. NapalMSX, con esta sabiduría concentrada pueden hacerse
demos que se muevan bastante bien en MSX...
Eduardo Robsy
_________________________________________________________________
¿Dónde se esconden l@s solter@s? Encuentra miles de perfiles en MSN Amor &
Amistad. http://match.msn.es/