He realizado la compresion de la rom de 48K, y posterior descompresion y salen identicas.
Hay un pequeño truquito con el LDI y el RET PO (un flash no muy usado, pero que usa LDI para indicar BC=#0000) y me he ahorrado algunos bytes
rutina compresora 62 bytes
rutina descompresora 26 bytes
Código: Seleccionar todo
;; Creada por Z80user
;; Compresor / Descompresor RLE
;; Comprime y Descomprime un bloque de datos RLE de memoria a memoria.
;;
;; Entrada a la rutina COMPRESORA:
;; HL = destino de los datos RLE.
;; IX = datos a comprimir
;; BC = tamaño de los datos a comprimir.
;; Salida
;; AF,DE desconocido
;; HL = HL+longitud de los datos comprimidos
;; IX = IX+BC
;;
;; Entrada a la rutina DESCOMPRESORA:
;; HL = dirección origen de los datos RLE.
;; DE = destino donde descomprimir los datos.
;; BC = tamaño de los datos a comprimir.
;; Salida
;; AF,DE desconocido
;; HL = HL+longitud de los datos descomprimidos
;; DE = DE+BC
;; 26 + 62 = 88
//-------------
org 16384
RLE_descompress
RLE_dec_loop
LD A,[HL] ; Leemos 1 byte
CP A,192
JR NC,RLE_dec ; si byte > 192 = está comprimido
test_end LDI ; Copiamos 1 byte en crudo
RET PO ; Volvemos si hemos terminado
JR RLE_dec_loop ; Repetimos el bucle
RLE_dec ; bucle para descompresión RLE
INC HL ; Nos colocamos en el valor
AND A,#3F
JR Z,test_end ; Si 192, es dato en crudo
PUSH BC
LD B,A ; B= numero de repeticiones
LD A,[HL]
bucle LD [DE],A ; \
INC DE ; Bucle de escritura B veces
DJNZ bucle ; /
POP BC
DEC BC ; Ajustamos el contador al usar RLE
JR test_end ; Copiamos 1 byte mas
//---------------
RLE_Comprimir
byte_1 LD E,[IX+#00] ; leer byte
INC IX ; incrementar posicion
DEC BC ; descontar contador
LD A,E ;
byte_2 CP A,#C0 ; Si es un codigo RLE
JR NC,RLE_compress ; tratar como RLE
CALL get_byte ; tomar el 2º byte
JR Z,ultimo_byte ; falta escribir el ultimo byte
CP A,E ;
JR Z,RLE_compress2 ; usar compresion RLE si son identicos
LD [HL],E ; son distintos, escribir el byte anterior
INC HL ;
LD E,A ; recuperar el ultimo byte leido
JR byte_2 ; continuar con la compresion
ultimo_byte LD [HL],E ; escribir el ultimo byte
INC HL ;
RET ; salir
RLE_compress2 LD D,#C1 ; eran identicos, empezar, con 2
JR RLE_Repetido
RLE_compress LD D,#C0 ; era un valor RLE original
RLE_Repetido CALL get_byte ; Obtener otro byte
JR Z,RLE_distinto ; Escribir el valor RLE si no hya mas bytes
CP A,E ; Comprobar si es identico
JR NZ,RLE_distinto ; Se encontro un byte distinto
INC D ; incrementar el contador de repeticiones
JR NZ,RLE_Repetido ; Otro byte identico
DEC D ; Se acabo el contador de repeticiones
RLE_distinto LD [HL],D ; \
INC HL ; \ escribir valor RLE
byte_simple LD [HL],E ; /
INC HL ; /
LD E,A ; Recuperar el ultimo byte distinto
JR byte_2 ; segir comprimiendo
get_byte LD A,B ; \
OR A,C ; Comprobar si es el ultimo byte
RET Z ; /
DEC BC ; descontar contador
LD A,[IX+#00] ; leer byte
INC IX ; incrementar posicion
RET ;Una posible mejora es indicar cuantos bytes hay en crudo, no solo los comprimidos, con un byte extra, pudiendo ahorrar algunos bytes, si los datos son mayores o iguales que el #C0

