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.
Le code source de cet utilitaire est disponible en téléchargement. Le code est suffisamment simple pour pouvoir être compilé sur une grande majorité de compilateur C.
Télécharger unccfi-1.0.tar.xz Taille du fichier : 12,4 ko
Pour décompresser l’archive :
tar xzvf unccfi-1.0.tar.xz
Une fois décompressée l'archive présente le dossier suivant :
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.
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.
#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;
}