Le fichier "Albator.Dsk" contient un exemple de slide-show pouvant être généré avec ConvImgCPC.
Pour cela, les images doivent être sauvegardées en mode "compacté". Ensuite, il suffit d'adapter le programme basic pour faire le slide-show.
Le fichier "dpkslide.bin" contient le programme binaire permettant d'afficher une image.

L'utilisation de dpkslide.bin est la suivante :
- Lire l'image compactée à l'adresse #2000
- Faire un CALL #A400 pour afficher l'image.
Le call #a400 décompacte l'image, affecte la palette et affiche l'image. Pour retourner au basic, il faut appuyer sur la touche espace.
Remarque: le programme utilise la plage mémoire #6400-#A3FF comme buffer temporaire de décompactage, avant d'afficher l'image. Tout ce qui se trouve dans cette plage d'adresse sera donc écrasé.

Lors d'une sauvegarde d'une image non compactée en mode CPC old, la palette est stockée à partir de l'adresse #D7D1, le mode écran est stocké en #D7D0, et une routine d'affichage est appelable par un call &C7D0.
Le programme d'affichage (situé à l'adresse #C7D0) est le suivant :
        LD      A,(#D7D0)
        CALL    #BD1C                   ; Changement de mode sans effacer l'écran
        LD      HL,#D7D1
        LD      B,(HL)
        LD      C,B
        CALL    #BC38                   ; Changement du Border
        XOR     A
        LD      HL,#D7D1
BCL:
        LD      B,(HL)
        LD      C, B
        PUSH    AF
        PUSH    HL
        CALL    #BC32                   ; Changement des Inks
        POP     HL
        POP     AF
        INC     HL
        INC     A                       ; passer à la couleur suivante
        CP      #10                     ; 16 couleurs effectuées ?
        JR      NZ,BCL                  ; sinon on reboucle
        JP      #BB18                   ; Attente appui d'une touche
Lors d'une sauvegarde d'une image non compactée en mode CPC+, la palette est stockée à partir de l'adresse #D7D1, le mode écran est stocké en #D7D0. Par contre, il n'y a pas de routine d'affichage directement incluse dans l'image.
Voici un exemple de programme d'affichage de la palette des images en mode CPC+ :
        LD      BC,#BC11                ; Port = #BCXX, 17 données à envoyer
        LD      HL,UnlockAsic           ; Séquence de déverouillage de l'ASIC
SetSeq:
        LD      A,(HL)
        OUT     (C),A                   ; Envoi des données
        INC     HL
        DEC     C
        JR      NZ,SetSeq
        LD      BC,#7FA0
        LD      A,(#D7D0)               ; Mode écran
        OR      #8C
        OUT     (C),A
        OUT     (C),C
        LD      BC,#7FB8
        OUT     (C),C
        LD      HL,#D7D1                ; Palette CPC+
        LD      de,#6400
        LD      BC,17*2
        LDIR
Boucle:                                 ; Attendre appui sur touche espace
        XOR     A
        LD      BC,#F40E                ; Registre 14 du PSG
        OUT     (C),C
        LD      BC,#F6C0                ; Ecriture numéro registre
        OUT     (C),C
        OUT     (C),A
        LD      BC,#F792                ; Port A PPI en lecture
        OUT     (C),C
        LD      BC,#F645                ; ligne = 5 (pour touche espace)
        OUT     (C),C
        LD      B,#F4                   ; Lecture registre
        IN      A,(C)                   ; Remarque : bit à 0 = appuyé
        LD      BC,#F782                ; Repasse port A PPI en écriture
        OUT     (C),C
        RLA                             ; Bit 7 dans Flag C
        JR      C,Boucle                ; Si pas à zéro, attendre
        EI
        RET

UnlockAsic:
        DB      #FF, #00, #FF, #77, #B3, #51, #A8, #D4
        DB      #62, #39, #9C, #46, #2B, #15, #8A, #CD, #EE
On doit ici interdire les interruptions pour maintenir les couleurs de l'Asic. On aurai pu également créer une routine d'interruptions, mais cela aurai alors un peu complexifié le source. J'ai préféré rester dans la simplicité.

Pour les images en "mode 3", l'astuce est de changer les stylots 1, 2, 3 de couleurs deux fois par lignes. Cela nécessite donc 6*200 = 1200 données de couleurs.
Les images en mode 3 ne peuvent être utilisées sur CPC qu'en mode compacté. En effet, sans cela, les images auraient eu une taille de 16384+1200=17584 octets, soit 18 Ko.
J'ai donc préféré utiliser uniquement ces images en mode compacté.

La compression RLE d'OCP ne permettai pas de gains significatifs sur les images. J'ai donc opté pour une compression dérivée du lzw, dont j'ai déjà donné le code source en C il y a quelques temps...
Cette routine de compression a plusieurs avantages :
- Le gain est plus important que la compression RLE,
- Le temps de décompression n'est pas beaucoups plus grand qu'avec une compression RLE,
- La routine de décompression est assez simple et a pu être facilement retranscrite en assembleur Z80.
Cette routine est livrée dans le package de ConvImgCPC dans le fichier "Depklzw.asm".
Voici cette routine :
;
; Entrée :
; - HL = Buffer (fichier compacté)
; - DE = Destination
; Sortie :
; - AF, BC, DE, HL modifiés
;
DepkLzw:
        XOR     A
        LD      (BclLzw+1),A
;
TstBitLzw:
        LD      A,(HL)
        INC     HL
        RRA                         ; Rotation rapide calcul seulement flag C
        SET     7,A                 ; Positionne bit 7 en gardant flag C
        LD      (BclLzw+1),A
        JR      C,TstCodeLzw

        LDI
;
BclLzw:
        LD      A,0
        RR      A                   ; Rotation avec calcul Flags C et Z
        LD      (BclLzw+1),A
        JR      Z,TstBitLzw
        JR      C,TstCodeLzw

        LDI
        JR      BclLzw
;
TstCodeLzw:
;
;       a = inbuffer[ inbytes ];
;
        LD      A,(HL)
        AND     A
;
; Plus d'octets à traiter
; = fini
;
        RET     Z

        INC     HL
        LD      B,A
        RLCA
        JR      NC,TstLzw40
;
;       length = 3 + ( ( inbuffer[ inbytes ] >> 4 ) & 7 );
;       index = ( inbuffer[ inbytes++ ] & 15 ) << 8;
;       index |= inbuffer[ inbytes++ ];
;       index++;
;
        PUSH    HL
        LD      C,(HL)                  ; C = poids faible index
        LD      L,B                     ; L = inbuffer[inbytes]
        RLCA
        RLCA
        RLCA
        AND     7
        ADD     A,3
        LD      H,A                     ; H = length
        LD      A,L
        AND     #0F
        LD      B,A                     ; B = poids fort index
        LD      A,H                     ; A = Length
        LD      H,D
        LD      L,E
        SBC     HL,BC
        DEC     HL
        LD      B,0
        LD      C,A
        LDIR
        POP     HL
        INC     HL
        JR      BclLzw
;
TstLzw40:
        RLCA
        JR      NC,TstLzw20
;
;       length = 2;
;       index = inbuffer[ inbytes++ ] & 0x3f;
;       index++;
;
        LD      C,B
        RES     6,C
        LD      B,0         ; BC = index -1, pas de +1 car flag C = 1
        PUSH    HL
        LD      H,D
        LD      L,E
        SBC     HL,BC
        LDI
        LDI
        POP     HL
        JR      BclLzw
;
TstLzw20:
        RLCA
        JR      NC,TstLzw10
;
;       length = 2 + ( inbuffer[ inbytes++ ] & 31 );
;       index = inbuffer[ inbytes++ ];
;       index++;
;
        PUSH    HL
        LD      A,B
        RES     5,A
        LD      C,(HL)                  ; C = index
        LD      B,0
        LD      H,D
        LD      L,E
        SBC     HL,BC
        ADD     A,2
        LD      C,A                     ; C = length
        LDIR
        POP     HL
        INC     HL
        JR      BclLzw

;
TstLzw10:
        RLCA
        JR      NC,CodeLzw0F
;
;       index = ( inbuffer[ inbytes++ ] & 15 ) << 8;
;       index |= inbuffer[ inbytes++ ];
;       length = inbuffer[ inbytes++ ] + 1;
;       index++;
;
        RES     4,B                     ; B = index(high)
        LD      C,(HL)                  ; C = index(low)
        INC     HL
        LD      A,(HL)                  ; A = length - 1
        PUSH    HL
        LD      H,D
        LD      L,E
        SBC     HL,BC                   ; Flag C=1 -> hl=hl-(bc+1)
        LD      B,0
        LD      C,A
        INC     BC                      ; BC = length
        LDIR
        POP     HL
        INC     HL
        JR      BclLzw
;
CodeLzw0F:
        PUSH    HL
        LD      A,B
        CP      #0F
        JR      NZ,CodeLzw02
;
;       length = index = inbuffer[ inbytes + 1 ] + 1;
;       inbytes += 2;
;
        LD      C,(HL)
        XOR     A
        LD      B,A
        INC     BC
        LD      H,D
        LD      L,E
        SBC     HL,BC
        LDIR
        POP     HL
        INC     HL
        JP      BclLzw
;
CodeLzw02:
        LD      H,D
        LD      L,E
        CP      2
        JR      C,CodeLzw01
;
;       length = index = inbuffer[ inbytes ];
;
        LD      C,A
        XOR     A
        LD      B,A
        SBC     HL,BC
        LDIR
        POP     HL
        JP      BclLzw
;
;       length = index = 256;
;
CodeLzw01:                              ; Ici, A = B = 1
        XOR     A
        LD      C,A
        DEC     H
        LDIR
        POP     HL
        JP      BclLzw
Pour le mode 3, seul la palette "CPC OLD" peut être utilisée pour le moment.
Pour terminer, voici le source qui permet d'afficher les images compactées en mode 0, 1, 2 ou 3, en version "CPC+" ou "CPC OLD" : Cette routine est livrée dans le package de ConvImgCPC dans le fichier "DpkSlide.asm".
BuffTmp EQU     #6400                   ; Buffer décompactage temporaire
BuffCmp EQU     #2000                   ; Buffer image compactée

        ORG     #A400

        ;
        ; Vérifier fichier est bien image compactée
        ;
        LD      HL,BuffCmp
        LD      A,(HL)                  ; Vérifier en-tête du fichier
        CP      'P'
        RET     NZ
        INC     HL
        LD      A,(HL)                  ; Doit commencer par "PKS"
        CP      'K'
        RET     NZ
        INC     HL
        LD      A,(HL)
        CP      'S'
        RET     NZ
        INC     HL
        LD      A,(HL)                  ; Puis, 4e octet = type d'image
        CP      'L'                     ; 'L' = image "normale"
        JR      Z,ImgType1
        CP      'P'                     ; 'P' = image CPC+
        JR      Z,ImgType2
        CP      '3'                     ; '3' = image "mode 3"
        JR      Z,ImgType3
        RET                             ; Si pas identifié, retour...

;
; Image type 1 - CPC "OLD" en mode 0, 1 ou 2
;
ImgType1:
        LD      HL,BuffCmp+21           ; Données image en #2015
        CALL    DecompImage
        EI
        LD      A,(BuffCmp+4)           ; Mode en #2004
        CALL    #BD1C                   ; Chgt Mode sans effacer l'écran
        LD      HL,BuffCmp+5            ; Palette en #2005
        XOR     A
SetCol:
        PUSH    AF
        PUSH    HL
        LD      B,(HL)
        LD      C,B
        CALL    #BC32                   ; Initialisation palette de couleurs
        POP     HL
        POP     AF
        INC     HL
        INC     A
        CP      16
        JR      C,SetCol
        JP      #BB18                   ; Attendre appui sur une touche

;
; Image type 2 - CPC + en mode 0, 1 ou 2
;
ImgType2:
        LD      HL,BuffCmp+37           ; Données image en #2025
        CALL    DecompImage
        LD      BC,#BC11
        LD      HL,UnlockAsic           ; Séquence de déverouillage de l'ASIC
SetSeq:
        LD      A,(HL)
        OUT     (C),A                   ; Envoi des données
        INC     HL
        DEC     C
        JR      NZ,SetSeq
        LD      BC,#7FB8
        LD      A,(BuffCmp+4)           ; Mode écran en #2004
        OUT     (C),A
        OUT     (C),C
        LD      HL,BuffCmp+5            ; Palette CPC+ en #2005
        LD      de,#6400
        LD      BC,16*2
        LDIR
        LD      HL,BuffCmp+5            ; Border = Couleur 0
        LDI
        LDI
Boucle:
        CALL    TstEspace               ; Test touche espace appuyée
        JR      C,Boucle                ; Si non, attendre
        LD      BC,#7FA0
        OUT     (C),C
        EI
        RET

;
; Image type 3 - CPC old en mode "3" (Mode 1 avec 6 couleurs/lignes)
;
ImgType3:
        LD      HL,BuffCmp+1206         ; Données image en #24B6
        CALL    DecompImage
        LD      HL,(#38)
        LD      (RestoreIRQ+1),HL       ; Sauvegarde ancien vecteur #38
        LD      HL,#C9FB
        LD      (#38),HL                ; EI et RET en #38
        LD      BC,#7F8D
        OUT     (C),C                   ; Mode 1
        XOR     A
        OUT     (C),A                   ; Sélectionner couleur 0
        LD      HL,BuffCmp+4            ; Adresse de la valeur de la couleur 0
        OUTI                            ; Et affecter
BoucleImg3:
        LD      B,#F5
WaitVBL:
        IN      A,(C)                   ; Attendre la VBL
        RRA
        JR      NC,WaitVBL
        CALL    TstEspace               ; test touche espace appuyée
        JR      NC,FIN                  ; si oui, fini
        EI
        HALT                            ; Attendre 2 interruptions
        HALT
        DI
        LD      B,158
Wait1:
        LD      HL,0                    ; Pause pour se synchroniser au début
        DJNZ    Wait1                   ; de l'écran visible
        XOR     A                       ; A = 0 pour tester fin des couleurs
        LD      BC,#7F01                ; C = ink 1
        LD      HL,BuffCmp+5            ; Palette en #2005
        LD      DE,#203                 ; D = ink 2, E = ink 3
SetCoul:
        OUT     (C),C                   ; ink 1
        OUTI
        OUT     (C),D                   ; ink 2
        OUTI
        OUT     (C),E                   ; ink 3
        OUTI
        NOP
        NOP                             ; Temps d'attente
        LD      BC,#7F01                ; Repositionner registre B
        OUT     (C),C                   ; ink 1
        OUTI
        OUT     (C),D                   ; ink 2
        OUTI
        OUT     (C),E                   ; ink 3
        OUTI
        CP      (HL)                    ; Valeur = 0 ?
        JR      NZ,SetCoul              ; Si non, on continue
        JR      BoucleImg3              ; Boucle attente touche

Fin:
        DI
RestoreIRQ:
        LD      HL,0
        LD      (#38),HL                ; Restaurer ancien vecteur #38
        EI
        RET

        ;
        ; Décompacter l'image dans un buffer temporaire
        ;
DecompImage:
        DI
        LD      DE,BuffTmp
        CALL    DepkLzw

        ;
        ; Efface l'écran (toutes les couleurs à 0)
        ;
        LD      BC,#7F54
        LD      A,#11
Cls:
        DEC     A
        OUT     (C),A
        OUT     (C),C
        JR      NZ,Cls

        ;
        ; Affiche la nouvelle image
        ;
        LD      DE,BuffTmp
        LD      HL,#C000
Draw1:
        LD      A,200
Draw2:
        EX      DE,HL
        LDI
        EX      DE,HL
        LD      BC,#7FF
        ADD     HL,BC
        JR      NC,Draw3
        LD      BC,#C050
        ADD     HL,BC
Draw3:
        DEC     A
        JR      NZ,Draw2
        LD      BC,#7CF
        SBC     HL,BC
        LD      A,L
        CP      #50
        JR      C,Draw1
        RET

;
; Lecture clavier (et notamment la touche espace...)
;
TstEspace:
        XOR     A
        LD      BC,#F40E                ; Registre 14 du PSG
        OUT     (C),C
        LD      BC,#F6C0                ; Ecriture numéro registre
        OUT     (C),C
        OUT     (C),A
        LD      BC,#F792                ; Port A PPI en lecture
        OUT     (C),C
        LD      BC,#F645                ; ligne = 5 (pour touche espace)
        OUT     (C),C
        LD      B,#F4                   ; Lecture registre
        IN      A,(C)
        LD      BC,#F782                ; Repasse port A PPI en écriture
        OUT     (C),C
        RLA                             ; Bit 7 dans Flag C
        RET

UnlockAsic:
        DB      #FF, #00, #FF, #77, #B3, #51, #A8, #D4
        DB      #62, #39, #9C, #46, #2B, #15, #8A, #CD, #EE

        read    "DepkLzw.asm"
Enfin, concernant les images en overscan, elles modifient les registres du CRTC avec les valeurs suivantes :
Registre 1  = #30 (48)
Registre 2  = #32 (50)
Registre 6  = #22 (34)
Registre 12 = #0D (13)
Une image non compactée est sauvegardée à l'adresse #200.
Le mode de l'image est stocké à l'adresse #800
La palete de l'image est stockée à partir de l'adresse #801
Le code d'affichage se trouve à l'adresse #811 pour une image en mode CPC OLD, et en #821 pour une image en mode CPC +.
Les fichiers "AffOverscan.asm" et "AffOverscan+.asm" contiennent respectivement les routine d'affichage décrites ci-dessus. Ce code effectue les actions suivantes :
- Modification des registres du CRTC pour prendre en compte l'overscan,
- Initialisation du mode et de la palette de couleurs
- Envoi de la séquence de dévérouillage de l'ASIC en mode CPC+
- Attente l'appui sur la touche ESPACE.

Les images compactées en mode Overscan sont sauvegardée avec la palette et le mode, mais sans la routine d'affichage.
Pour les décompacter, il faut utiliser la routine décrite dans le le fichier "Depklzw.asm", et positionner ensuite le CRTC, le mode et la palette de couleurs.