P.D: No comprendo lo de engañar. Que quieres engañarle con la cabecera o algo diciendole "que esta comprimido" cuando en realidad no lo esta o al menos no por el mismo metodo... MISSA NO ENTIENDEE
Missa explica si tussa comprende no bueno (aunque sé por experiencia que nadie lo va a entender, ni yo mismo cuando lo relea).
En las compresiones siempre hay unos bits que te dicen lo que hay que hacer. En los casos más sencillo, antes de los bytes comprimidos va un byte de flags, donde normalmente se indica con un 0 que hay un byte sin comprimir y con un 1 que hay que copiar datos de una dirección. Se ve mejor con un ejemplo. Imagina que un fichero comprimido tiene los bytes 0A-00-01-02-03-04-05-06-07-08-09-0A-0B-0C (los valores están puestos a propósito para verlo mejor). El primer byte son los flags, 0A, que en binario es 00001010. Interpretando por orden, de izquierda a derecha::
0 - copiar el byte siguiente, en este caso el 00
0 - copiar el byte siguiente, en este caso el 01
0 - copiar el byte siguiente, en este caso el 02
0 - copiar el byte siguiente, en este caso el 03
1 - coger los dos bytes siguientes, en este caso 0405 (que podría ser interpretado como coger 5 bytes de 040 posiciones más atrás)
0 - copiar el byte siguiente, en este caso el 06
1 - coger los dos bytes siguientes, en este caso 0708 (que podría ser interpretado como coger 8 bytes de 070 posiciones más atrás)
0 - copiar el byte siguiente, en este caso el 09
Al final nos daría algo así como 00-01-02-03-X1-X2-X3-X4-X5-06-Y1-Y2-Y3-Y4-Y5-Y6-Y7-Y8-09, 19 bytes que se han formado con 11 (los valores de X/Y serían unos bytes que estarían ya en el fichero).
Estos unos y ceros sirven para "engañar" a las rutinas de compresión. Imagina que tenemos que comprimir "¡ESTOY HACIENDO UN FAKE!" y no sabemos cómo hacerlo. Pues aquí usamos el truco del cero, poniendo siempre 0 en los flags para que copie los bytes tal como están, teniendo en cuenta que los datos hay que copiarlos de 8 en 8, justo los bits que hay en un byte:
00-¡-E-S-T-O-Y- -H
00-A-C-I-E-N-D-O-
00-U-N- -F-A-K-E-! (pongo las letras en vez de los ASCII por comodidad).
A la hora de descompimir, el programa lee los flags, en este caso siempre leerá ceros, y eso le indica que tiene que coger 8 bytes tal y como están. Obviamente, el programa "comprimido" ocupa más que el original, exactamente 1/8 más, pero es un método que funciona y más de una vez te saca de un apuro. Bueno, éste es el método fácil. Hay otros más complicados, que dependen de la rutina de compresión usada, como el de Legend of Mana de PSX, donde podemos indicar 240 bytes en vez de 8 por cada flag, pero básicamente siempre es lo mismo: uno o varios bytes flags que nos indican cuántos bytes tenemos que leer y poner tal cual. Realmente no es que estemos engañando al programa, lo que ocurre es que usamos sólo uno de los códigos que indican la compresión, justo el que dice "dato no comprimido".
Volviendo a los ADT de marras, me temo que no se puede hacer, al menos no tan fácilmente. Por lo que he visto del programa ése de la wiki, es alguna variante de la compresión huffman. De hecho, la rutina de descompresión tiene una estructura prácticamente idéntica a la huffman, pero trata el fichero por partes en vez de hacerlo entero. Si alguien se quiere meter con ello, que el nene dice que nanay, puede ver la decompresión en el programa:
- int curBitfield = readSrcBitfieldArray(&array2, tmpBufLen);
- if (curBitfield < 256) {
- dstPointer[dstOffset++] =
- tmp16k[tmp16kOffset++] = curBitfield;
- tmp16kOffset &= 0x3fff;
- } else {
- int i;
- int numValues = curBitfield - 0xfd;
- int startOffset;
- curBitfield = readSrcBitfieldArray(&array3, tmpBufLen1);
- if (curBitfield != 0) {
- int numBits = curBitfield-1;
- curBitfield = readSrcBits(numBits) & 0xffff;
- curBitfield += 1<<numBits;
- }
-
- startOffset = (tmp16kOffset-curBitfield-1) & 0x3fff;
- for (i=0; i<numValues; i++) {
- dstPointer[dstOffset++] = tmp16k[tmp16kOffset++] =
- tmp16k[startOffset++];
- startOffset &= 0x3fff;
- tmp16kOffset &= 0x3fff;
- }
- }
-
- curBlockLength++;
y compararla con la que se hace por Huffman:
- c = DecodeChar();
- if (c < 256) {
- if (putc(c, outfile) == EOF) Error(wterr);
- text_buf[r++] = c;
- r &= (N - 1);
- count++;
- } else {
- i = (r - DecodePosition() - 1) & (N - 1);
- j = c - 255 + THRESHOLD;
- for (k = 0; k < j; k++) {
- c = text_buf[(i + k) & (N - 1)];
- if (putc(c, outfile) == EOF) Error(wterr);
- text_buf[r++] = c;
- r &= (N - 1);
- count++;
- }
Son exactamente iguales, tan sólo han cambiado los nombres de las variables y funciones. El problema está en el proceso previo, donde espero que alguien sea capaz de entenderlo, que yo me pierdo.
Como curiosidad, y ya que hemos tocado el tema, aquí no se emplean los ceros para indicar que copie los bytes tal cual. En este caso es un valor de 16 bits menor de 256. En cristiano: un cero seguido de un valor indica que se tome un byte tal cual. Pero para conseguir ese valor de 16 bits hay que hacer un montón de cosas.
~~~ AÑADIDO ~~~
Estaba yo pensando (es que me he dado un golpe en la cabeza, no penséis que es algo normal en mí) que si la versión PC usa los mismos archivos, ¿qué problema hay en dar el cambiazo? Si no recuerdo mal tanto la versión PC como la versión PSX salieron en cristiano y si los ADT tienen el mismo formato debería ser algo sencillo de hacer, a no ser que algo se me escape.