[C] Descompresión LZSS

Revela aquí tus conocimientos o plasma tus dudas acerca de temas relacionados con los lenguajes de programación. Tan útiles a la hora de hacer nuestras propias herramientas.

Moderador: Faloppa

[C] Descompresión LZSS

Notapor DaRKWiZaRDX » Sab Feb 19, 2011 6:03 am

Buenas!
Les dejo el código en C que usé para descomprimir LZSS (o es otra variante? alguien que me asesore por si me confundí de algoritmo!) en Lord of The Rings. Quizás a alguien le sirva.
El código tiene ya un par de años y seguramente le falten muuuuchas optimizaciones, pero cumplió con su cometido en su momento, además tiene varias cosas hardcodeadas (direcciones, nombre de Rom, etc.)

El buffer utilizado es de $1000 bytes.

Código: Seleccionar todo
#include <stdio.h>
#define INICIO_DATOS_COMPRIMIDOS 0x360A6

 unsigned char byte_pattern; //pattern
 unsigned char cant_a_traer; //cantidad a traer de LZ
 unsigned int i,x = 0,z = 0,lectura_de_buffer,cant_bytes_descomprimidos,total_leidos = 0;   // x lo uso para moverme por la zona de datos descomprimidos, z para moverme dentro del buffer. Lectura de buffer es el offset al que tengo que desplazarme dentro del buffer para traer datos repetidos.
 unsigned char decomp[64000];
 unsigned char buffer[0x1000];
 unsigned char a,b;
 bool haybyte = 0;

int main() {
 FILE *rom = fopen("lotr.smc","rb");
 FILE *out = fopen("decomp.bin","w+b");
 if (!rom || !out) {
   printf("no se pudieron abrir/crear los ficheros.");
   getchar();
   return 1;
 }
 fseek(rom,INICIO_DATOS_COMPRIMIDOS,SEEK_SET);
 for (i = 0; i != 0x1000; i++) {
    buffer[i] = 0;      // llena el buffer de 0
 }
 cant_bytes_descomprimidos =  fgetc(rom);
 cant_bytes_descomprimidos += fgetc(rom) << 8;     // los datos se leen en big-endian

 total_leidos+=2
 
 while(x <= cant_bytes_descomprimidos && !feof(rom)) {
   byte_pattern = fgetc(rom); //lee byte para pattern
   total_leidos++;
   b = 0x01;

   for(i = 8; i != 0; i--) {   // recorro los 8 bits del byte de pattern
     if (byte_pattern & b) {   // si es una letra común
       a = fgetc(rom);
       total_leidos++;
       decomp[x++] = a;
       buffer[z++] = a;
       b = b << 1;
     }
     else {             // si es una trama comprimida
       lectura_de_buffer = fgetc(rom);
       total_leidos++;
       a = fgetc(rom);
       total_leidos++;
       lectura_de_buffer += (a << 8);   // leo cantidad de bytes a traer+offset (big-endian), falta separarlo en Offset y cantidad de bytes

       cant_a_traer = ((lectura_de_buffer & 0xf000) >> 12) +3;  // los muevo a la parte baja de la variable, y sumo 3 (mínimo de letras para utilizar compresión, sino no se justifica)

       lectura_de_buffer = lectura_de_buffer & 0x0fff;     // el resto de los bits los uso para el offset al que deberé desplazarme para traer los datos

       while (cant_a_traer){
           decomp[x++] = buffer[lectura_de_buffer];
           buffer[z++] = buffer[lectura_de_buffer++];    // traigo datos del buffer
           if (z == 0x1000) z = 0;
           if (lectura_de_buffer == 0x1000) lectura_de_buffer = 0;   // compruebo si llegué al final del buffer, entonces vuelvo al principio
           cant_a_traer--;
       }
     b = b << 1;   // me muevo al siguiente bit del byte de pattern
     } // leo próximo byte de pattern
   }
 }
 fwrite(decomp,sizeof(decomp),1,out);   
 fclose(rom);
 fclose(out); //guardo datos en archivos y los cierro
 printf("terminado. %d bytes leídos y %d bytes descomprimidos",total_leidos,x); // mensaje final
 getchar();
 return 1;
}


El código es un completo quilombo, si tengo más tiempo y me acuerdo lo emprolijo un poco, pero CREO que la idea debería entenderse.
Espero que le sirva a alguien. Cualquier consulta acá o al mail.
¡Saludos!
Avatar de Usuario
DaRKWiZaRDX
Usuario
Usuario
 
Mensajes: 222
Registrado: Jue Ene 18, 2007 9:49 pm
Ubicación: Argentina

Re: [C] Descompresión LZSS

Notapor Lord Raptor/PkT » Sab Mar 23, 2013 1:15 am

Una pekeña petición...
Serías tan amable de subirlo ya kompilado ?

Gracias, un saludo
-------------------------------
  ... por ké kuesta más pagarse un entierro, ke kobrarse una vida ?!!? ...
-------------------------------
Avatar de Usuario
Lord Raptor/PkT
Usuario
Usuario
 
Mensajes: 62
Registrado: Lun Ene 28, 2008 8:34 pm
Ubicación: En el Lado Oskuro ....


Volver a Programación

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron