minter escribió:El Exomizer Coloca el bloque comprimido al principio de la memoria y empieza a descomprimir desde el final hasta el principio.
Mientras que el de Antonio lo hace del revés. Carga el bloque comprimido al final de la memoria y va descomprimiendo desde el principio al final.
Debe de estar esa ganancia de velocidad relacionada con el contador del programa y no con el método de compresión.
Le debe resultar mas rápido al ordenador volver a situarse al principio para dejar la memoria descomprimida, que leer al principio y ir escribiendo en el final.
Complejidad para el uso de punteros de 16 bits en procesador 6502Es sabido que el 6502 (o sus variantes 6510/7501/8500/8501/8502) es un procesador de 8 bits con
solo 3 registros de 8 bits (A,X,Y) con los que tienes que hacer malabarismos apoyados en memoria, para hacer cualquier cálculo matemático serio. Por lo tanto debes usar 2 direcciones de memoria seguidas que almacenen el byte bajo y el byte alto del puntero de 16 bits; en el 6502 esto se
debe se hace en página cero (los primeros 256 bytes de RAM) porque el juego de instrucciones incorpora un modo de direccionamiento especial para usar esa zona de memoria ahorrandote ciclos, pero las capacidades son muy limitadas pues el 6502 no es apenas
ortogonal. Algunas de estas limitaciones se mejoraron en el 65C02 (Apple IIc, Acorn BBC Master, Atari Lynx) y en el 65C816 (Apple II
GS, Super Nintendo). Pero bueno, ya hablé de ello en mi hilo
Z80 vs 6502/6510 vs 65C02.
Por lo tanto, si queremos traducir la instrucción en lenguaje C:
*destino++ = *origen++ para copiar un byte de memoria y postincrementar los punteros, algo que en Z80 se haría con una simple instrucción
LDI pues en 6502 tenemos que armar todo un cristo, encima asegurandonos todo el rato que Y sea cero, porque el C64 no tiene direccionamiento indirecto sin depender de Y:
LDA (ptr_origen),Y
INC ptr_origen ; Byte bajo
BNE +
INC ptr_origen+1 ; Byte alto
+ STA (ptr_destino),Y
INC ptr_destino ; Byte bajo
BNE ++
INC prt_destino+1 ; Byte alto
++ ...
Si queremos realizar la rutina inversa, que vaya descomprimiendo al revés, lo que vendría a ser
*destino-- = *origen-- postdecrementando los punteros, que en Z80 se haría con
LDD, pues en 6502 se complica en demasía debido a que la bandera de cero (Z) solo se activa cuando el resultado es cero, y cuando llegamos a una dirección $XX00, todavía debemos copiar ese byte antes de pasar a la página inferior $YYFF, siendo Y=X-1 ... no sé si me explico bien. Tampoco podemos usar la bandera de negativo (N) porque ésta estaría activa para todos los casos entre $80 y $FF. Por lo tanto debemos comprobar antes el valor del byte y usar la función de
resta en vez de la función de decrementado, con lo que perdemos
demasiados ciclos de reloj (tiempo de CPU).
LDA (ptr_origen),Y
TAX ; Guardamos valor obtenido porque las restas necesitan el acumulador
SEC
LDA ptr_origen ; Byte bajo
SBC #1
STA ptr_origen ; Byte bajo
BCC +
DEC ptr_origen+1 ; Byte alto
+ TXA ; Recuperamos el valor. No existe la instrucción STX (NN),Y
STA (ptr_destino),Y
SEC
LDA ptr_destino ; Byte bajo
SBC #1
STA ptr_destino ; Byte bajo
BCC ++
DEC ptr_destino+1 ; Byte alto
++ ...
Exomizer lo que hace es jugar con el registro Y, hacerlo variar entre 0 y 255, para sumarlo al puntero. Pero implica una rutina diferente que no use Y para otras cosas a lo largo de su código de descompresión. No sé si esta rutina se podría optimizar... le ando dando vueltas, pero veo mala solución.