unccfi

Le programme unccfi est un outil en ligne de commande développé en C qui permet de décompresser les images disques .CFI produites par l'utilitaire FDCOPY.COM d'Amstrad.

Il est placé sous licence GNU GPL v3.

L'utilitaire FDCOPY.COM d'Amstrad permet de compresser des images de disquettes en utilisant un algorithme de type RLE (Run-length encoding). La mise en œuvre est simple, nécessite peu de puissance de calcul et demeure très efficace sur des images disques.

Le format de ces fichiers est également simplifié à l'extrême. Il est décrit sur la page FDCOPY file format

unccfi ne permet que la décompression de ces fichiers.

Téléchargement

Pour récupérer l'archive contenant unccfi, cliquez sur le lien suivant :

Télécharger unccfi-1.0.tar.gz

Compilation

Pour décompresser l'archive :

tar xzvf unccfi-1.0.tar.gz

Une fois décompressée l'archive présente le dossier suivant :

unccfi-1.0
├── COPYING     Licence GNU GPLv3
├── Makefile    Fichier Makefile pour la compilation
└── unccfi.c    Code source de unccfi

Pour compiler unccfi, vous devez disposer du compilateur gcc, une installation minimale étant suffisante. Placez-vous dans le répertoire unccfi-1.0 et tapez la commande suivante :

make unccfi

Si tout se passe bien, un exécutable unccfi est créé dans le répertoire.

Utilisation

Pour utiliser unccfi, il faut que l'exécutable soit dans un répertoire pointé par la variable d'environnement PATH ou préciser son chemin complet lors de l'appel.

L'utilitaire est basique. Il prend un fichier .CFI en entrée standard et le décompresse sur la sortie standard.

Il peut être utilisé de la façon suivante :

cat FILE.CFI | unccfi > FILE.IMG

Il faut bien sûr remplacer FILE.CFI par la fichier à décompresser et FILE.IMG par le nom du fichier que l'on cherche à créer.

Code source

Voici un extrait du code source de unccfi débarrassé des commentaires généraux :

#include <stdio.h>

int main() {
    while(!feof(stdin)) {
        /* The CFI file is composed of tracks which starts with the track
         * length 
         */
        int tracklength = getchar() + 256 * getchar();

        while(tracklength > 0) {
            /* A track is composed of compressed or uncompressed blocks */
            int blocklength = getchar() + getchar() * 256;

            /* Checks whether the block is compressed or not */
            if(blocklength >= 0x8000) {
                int torepeat;

                /* The block is compressed, it occupies 3 bytes */
                tracklength -= 3;

                /* Calculate the number of repeats */
                blocklength -= 0x8000;

                /* Get the byte to repeat */
                torepeat = getchar();

                /* Output the character blocklength times */
                for(; blocklength > 0; blocklength--) putchar(torepeat);
            } else {
                /* The block is uncompressed */
                /* It occupies blocklength + 2 bytes */
                tracklength -= blocklength + 2;

                /* Directly stream blocklength bytes from stdin to stdout */
                for(; blocklength > 0; blocklength--) putchar(getchar());
            }
        }
    }

    /* Everything went well, maybe */
    return 0;
}