Introduction à la Programmation de Demos C-64

PROGRAMMATION DU COMMODORE-64

Une petite introduction à la démo-intro :

Poursuivant notre apprentissage de l’assembleur du C-64 et dans le souci d’être le plus concret possible je vous propose un tutoriel complet sur l’écriture de petites Intros (comme des cracktros), passage obliger avant d’envisager d’écrire des démos plus ambitieuses.

Tout en présentant quelques fragments de codes, on en profitera pour voir quelques techniques de base en assembleur MOS65xx.

Notre point de départ sera le petit programme vu pour afficher du texte lors la section sur l’assembleur TMP et le cross-assembleur TMPx.

*= $801

.BYTE $0B,08,$0A,$00,$9E,$32,$30,$36,$34,$00         ; BASIC 10 SYS2064

*= $810

START

      ; EFFACE L'ECRAN

      JSR $E544               ; Appel de ClearScreen

      ; ECRAN NOIRE

      LDA #$00

      STA $D020

      STA $D021

; ON AFFICHE NOTRE TEXT QUI DOIT SE TERMINER PAR UN 0

      LDX #$00                ; X COMME INDEX

      LDA TEXT1               ; CHARGE DANS A le premier caractère de notre texte

LOOPTEXT

      ; POSITION DANS LA MEMOIRE ECRAN: Y=8 X=8 MEM= Y*40+X -> 320+8 =352 + 1024 (base) = 1376

      STA 8*40+1024+8,X       ; Afficher à l'écran le caractère en L=8 et C=8+index X

      INX                     ; Incrémente l'index

      LDA TEXT1,X             ; Caractère suivant

      BNE LOOPTEXT            ; Si diffèrent de 0 on boucle

                             ; Sinon on a fini

; ON ATTEND QU'UNE TOUCHE BREAK OU SPACE SOIT APPUYER

WAITBRK

      LDA $DC01        

      CMP #$FF         

      BEQ WAITBRK

      ; UNE INSTRUCTION BRK SUFFIT POUR RETABLIR L’ETAT D’AVANT PROGRAMME

      BRK

TEXT1

      .TEXT "PREMIERE INTRO C-64 !"      ; Le texte que nous afficherons

      .BYTE $00                          ; Doit se terminer par 0

 

Je pars du principe que nous avons parfaitement compris ce programme.

C’est-à-dire  que nous maitrisons la lecture et l’écriture mémoire en adressage direct et indexe.

Nous savons faire appel à des sous-routines. Nous maitrisons les branchements directs et conditionnels de base (BEQ, BNE) 

Avant d’aller plus loin soyons certain d’avoir bien compris ce programme.

Le timing et la synchronisation avec l’écran

Temporisation manuelle :

Supposons que nous voulions écrire un petit programme qui affiche tout l’écran en noire pendant quelques secondes, ensuite laisse réapparaitre l’écran de fond. Avec tout ce que nous savons, on est en mesure de produire une petite routine d’attente et peu comme celle-ci-dessous.

WAITSHORT:

            LDX #$00

      .LOOP:

INX

            BNE .LOOP

            RTS

 

Nous savons qu’une instruction prend un certain nombre de cycle pour s’exécuter, nous sommes en mesure de calculer le temps de temporisation d’un appel à cette routines. INX et LDX #val prennent 2 cycles, RTS prend 6 cycles enfin une instruction de branchement relatif prend 3 cycles si le branchement est effectué et 2 cycles dans le cas contraire.

On a donc 2(LDX #) + 6 (RTS) + 4(INX BNE SANS BRANCHEMENT) + 254*(5) (INX BNE avec branchement) = 1282 cycles.

Il convient également de rajouter 6 cycles d’appel (instruction JSR) soit 1288 que l’on converti en seconde en divisant par la fréquence du 6510 (985248 HZ en PAL) soit 1,3ms ce qui est bien trop court.

 

Ci-dessous une routine un peu plus longue utilisant ce qu’on appelle une boucle imbrique (plus simplement une boucle qui contient une autre boucle) et qui sauve le registre X. Le registre Y sera le paramètre d’attente à fixer avant d’appeler la fonction.

 

WAITFUNC:

      PHA         ; EMPILE A

      TXA

      PHA         ; EMPILE X

      LDX #$00

.LOOP:

      INX

      BNE .LOOP

      DEY

      BNE .LOOP

      PLA        

      TAX         ; DEPILE X

      PLA         ; DEPILE A

      RTS

Cette petite routine prend exactement : (Y*1282 + 24) cycles à s’exécuter auquel on rajoute 8 cycles supplémentaire pour l’écriture du registre Y (2 cycles) et l’appel à la fonction (6 cycles). Soit environ 0,33 secondes pour Y=$FF.

Cela reste quand même trop court donc il nous faut rajouter une 3eme boucle imbriqué avec le registre A. La valeur de Y définira la durée de l’attente.

WAITLONG:

      PHA

      TXA        

      PHA         ; SAUVE X

      LDA #$00               

      TAX                         

      CLC                         

.LOOP:

                  INX              

                  BNE .LOOP  

            ADC #1

            BNE .LOOP

      DEY              

      BNE .LOOP  

      PLA

      TAX         ; RESTAURE X

      PLA         ; RESTAURE A     

      RTS  

Si Y vaut 0 la durée d’attente sera de 324902 + (255)* 324875 soit 83168027 cycles c’est-à-dire 87,5 secondes.

Sinon la formule T = 27 + Y*324902 nous donnera le nombre de cycle à attendre. Par exemple si Y=6 on aura 1 949 439 cycles soit nos 2 secondes recherchée.

La formule Y = (T*985248 - 27) / 324902 nous permet de déterminer la valeur de Y en fonction du Temps d’attente désirée en seconde. Par exemple pour 10 secondes, la valeur de Y sera de 30.

 

Les registres $D012/$D011 et la synchronisation avec l’écran

Pour générer une image, le C64 envoie des signaux au moniteur qui va répondre en balayant avec son canon à électron l’écran horizontalement de gauche à droite et de haut en bas et ainsi générer une image. A chaque ligne horizontale, le canon balai l’écran de gauche à droite, et lorsque il reçoit du C64 un signal de retour horizontale, le canon revient en position gauche une ligne en dessous. Au bout d’un certain nombre de ligne générée, le C64 renvoi un signal de retour verticale : le canon va revenir à sa position initiale et recommencer à balayer l’écran de gauche à droite et de bas en haut. Le cycle se répète 50 fois par seconde sur un C-64 PAL.

Grace au registre $D012 et $D011 nous avons la possibilité de surveiller la position actuelle du balayage horizontale. Cette valeur est codée sur 9 bits où les 8 dernier bits sont contenues dans le registre $D012 et le bit le plus significatifs dans le bit 7 du registre $D011.  La lecture de ces registres non seulement nous renseigne sur l’état de génération de l’image mais nous permets également d’avoir une première référence de temps.

En fait, la valeur lue dans ce registre ne correspond pas exactement à la position de la ligne visible à l’écran. Tout d’abord appelons la valeur contenue dans la registre $D011/$D012 « Raster ». Sans trop rentrer dans les détails nous avons sur un C-64 en PAL 312 lignes générées dont seulement 284 sont visibles. Par default, la premier ligne de l’écran de fond démarre en Raster 51($33) et la dernière ligne en 250 ($FA).

Le retour vertical (Vertical-sync) démarre en raster 300 ($12C) et la fin du retour vertical en raster 15($0F).

Et donc, le bord haut de l’écran commence en raster 16 pour se terminer en raster 50 et le bord bas démarre en raster 251 et se termine en  raster 299 ($12B).

 

Normalement une ligne verticale prend 63 cycles de façon transparente pour le processeur qui a accès à 63 cycles par ligne de raster. Mais une ligne sur 8 va « voler » au processeur au moins 40 cycles supplémentaires. Cette ligne est appelé BAD LINE elle est charge de charger (en anglais on rencontre le verbe « Fetch ») les informations relative aux couleurs et aux Sprites (Lutins).  Nous y reviendrons un peu plus tard.

 

Retenons seulement que Le retour vertical (Vertical-sync) démarre lorsque la valeur du raster est égale à 300 ($12C) et que la dernière ligne de fond correspond à la valeur 250 ($FA).

Grace à ces informations nous sommes en mesures d’écrire des petites routines qui se chargeront d’attendre plus ou moins un retour vertical avant de rendre la main.

Ci-dessous 3 routines de synchronisation. Attention la deuxième routine est juste un exemple d’erreur classique ne fonctionne pas tout à fait.

 

; VSYNC1 qui rend la main en ligne 252 donc lorsque l’écran de fond a été généré.

VSYNC1 

      LDA #$FB          ; 251

_LOOP

CMP $D012         ; Compare avec le registre D011

      BCS _LOOP         ; SI $D012<=251 on attend.

      RTS

 

; VSYNC2 qui est censé rendre la main lors du démarrage d’un retour vertical

; ATTENTION Cette routine n’est pas efficace

; Si cette routine est appelée au moment où la ligne 301 est en cours de génération

; La routine va alors attendre en réalité la ligne 44 pour rendre la main.

; Voir VSYNC3 pour la solution. 

VSYNC2 

      LDA $D011

ROL A             ; B7 dans CARRY

      BCC VSYNC2        ; B7 éteint on attend

      LDA #44           ; 44+256=300 

_LOOP

CMP $D012         ; Compare avec le registre D011

      BCS _LOOP         ; SI $D012<=44 on attend.

      RTS

 

; VSYNC3 rend la main lors du démarrage d’un retour verticale

; Contrairement à VSYNC2, la routine rend la main exactement (enfin presque)

; Lorsque le retour vertical démarre.

VSYNC3 

      LDA $D011

ROL A             ; B7 dans CARRY

      BCS VSYNC3        ; B7 Allumée on attend

_LOOP

      LDA $D011

ROL A             ; B7 dans CARRY

      BCC               ; B7 éteint, on attend

      LDA #44           ; 44+256=300 

_LOOP2

CMP $D012         ; Compare avec le registre D011

      BCS _LOOP         ; SI $D012<=44 on attend.

 

VSYNC1 et VSYNC3 sont réellement utile. VSYNC2 est là pour illustrer un problème que l’on rencontre sur beaucoup de plateforme : il ne suffit pas d’attendre un retour vertical il faut être sur de rendre la main au moment où le retour vertical commence ! Si l’on ne fait que tester si nous sommes dans un retour vertical rien ne garantit qu’en sortie de fonction le retour vertical ne se soit pas terminer. Sur le C-64 les registres Raster nous renseignent sur l’exact retour vertical (contrairement à d’autre plateforme comme le VGA sous PC) mais il nous faut tester deux registres raster ($D012 et le bit 7 du registre $D011). VSYNC3 tente de simplifier le problème en attendant exactement la ligne 256 avant d’attendre la ligne 300.

 

Comme exercice je vous propose d’optimiser la partie ou l’on test le bit 7 du registre $D011, c’est-à-dire remplacer :

VSYNC3 

      LDA $D011

ROL A             ; B7 dans CARRY

      BCS VSYNC3        ; B7 Allumée on attend

_LOOP

      LDA $D011

ROL A             ; B7 dans CARRY

      BCC _LOOP         ; B7 éteint, on attend

Par quelque chose de mieux (plus court et plus rapide.) Tips : examinez le jeu d’instruction du MOS65xx et regardez s’il n’existe pas une instruction qui va tester le bit 7 en mémoire sans affecter le contenu de celle-ci.

Remarquez également que VSYNC3 sera plus « lent » que VSYNC1.

 

QUELQUES EFFETS SIMPLE

Grace aux petites routines de synchronisation, nous allons pouvoir produire quelques petits effets classiques.

FLASH SCREEN

 

Grace à la routine VSYN3 on va pouvoir faire flasher tout l’écran sans artefact. Il suffit simplement d’appeler la routine avant de changer la couleur de fond.

*= $801

.BYTE $0B,08,$0A,$00,$9E,$32,$30,$36,$34,$00         ; BASIC 10 SYS2064

*= $810

START

      ; DESACTIVE L’ECRAN DE FOND

      LDA $D011

      AND #$EF          ; ETEINT LE BIT 4

      STA $D011         ; POUR DESACTIVER LE FOND

      ; SAUVE LA COULEUR DE FOND

      LDA $D020

      STA SAVECOLOR

      ; PARTIE PRINCIPALE

MAIN

      ; LDY #$02        ;

      ; JSR WAITLONG    ; ALONGEMENT DE L’EFFET

JSR VSYNC3        ; ON SE PLACE DANS UN RETOUR VERTICAL

      ; CHANGEMENT DE COULEUR

INC $D020         ; ON INCREMENTE LA COULEUR

; VERIFIE TOUCHE CLAVIER STOP/ESPACE/1/Q/BACK ARROW/ETC

LDA $DC01

CMP #$FF

BEQ MAIN

      ; QUITTE ET RESTAURE LA COULEUR ET L’ETAT INITIAL DU VIC

      BRK

SAVECOLOR

      .BYTE 0

; SYNCRONISATION VERTICAL

VSYNC3 

BIT $D011         ; B7 DANS N

BMI VSYNC3        ; B7 Allumée on attend

LOOP

BIT $D011         ; B7 DANS N

BPL LOOP          ; B7 éteint, on attend

LDA #44           ; 44+256=300 

LOOP2

CMP $D012         ; Compare avec le registre D011

BCS LOOP2         ; SI $D012<=44 on attend.

RTS

           

 

COLOR TABLE SCREEN

Plus intéressant maintenant on fait appel à une table de couleur dans lequel on choisir divers valeurs qui va dépendre de l’effet que nous voulons produire.

Ci-dessous, un exemple de « Fade to white. Fade to black ».

 

*= $801

.BYTE $0B,08,$0A,$00,$9E,$32,$30,$36,$34,$00         ; BASIC 10 SYS2064

*= $810

START

      ; DESACTIVE L’ECRAN DE FOND

      LDA $D011

      AND #$EF          ; ETEINT LE BIT 4

      STA $D011         ; POUR DESACTIVER LE FOND

      ; SAUVE LA COULEUR DE FON

      LDA $D020

      STA SAVECOLOR

      ; PARTIE PRINCIPALE

MAIN

      LDY #$01

      JSR WAITLONGFUNC

JSR VSYNC3        ; ON SE PLACE DANS UN RETOUR VERTICAL

      ; CHANGEMENT DE COULEUR X INDEX COURANT

LDA COLORTAB,X    ; CHARGE LA COULEUR DE LA TABLE

STA $D020         ; CHANGE

INX               ; INCREMENTE INDEX

TXA               ; INDEX DANS A

AND #$3F          ; A&63 pour 0<=A<63

TAX               ; INDEX DANS X

; VERIFIE TOUCHE CLAVIER STOP/ESPACE/1/Q/BACK ARROW/ETC

LDA $DC01

CMP #$FF

BEQ MAIN

      ; QUITTE ET RESTAURE LA COULEUR ET L’ETAT INITIAL DU VIC

      BRK

SAVECOLOR

      .BYTE 0

; TABLE DE 64 COULEURS FADE TO WHITE FADE TO BLACK

COLORTAB

      .BYTE 0,0,0,0                ;4    NOIRE

      .BYTE 11,11,11,11            ;8    GRIS FRONCE

      .BYTE 12,12,12,12            ;12   GRIS MOYEN

      .BYTE 15,15,15,15            ;16   GRIS CLAIRE

      .BYTE 1,1,1,1                ;20   BLANC

      .BYTE 1,1,1,1                ;24

      .BYTE 1,1,1,1                ;28

      .BYTE 1,1,1,1                 ;32

      .BYTE 1,1,1,1                ;38

      .BYTE 15,15,15,15            ;40

      .BYTE 12,12,12,12            ;44

      .BYTE 11,11,11,11            ;48

      .BYTE 0,0,0,0                ;52

      .BYTE 0,0,0,0                ;56

      .BYTE 0,0,0,0                ;60

      .BYTE 0,0,0,0                ;64

; SYNCRONISATION VERTICAL

VSYNC3 

BIT $D011         ; B7 DANS N

BMI VSYNC3        ; B7 Allumée on attend

_LOOP

BIT $D011         ; B7 DANS N

BPL _LOOP         ; B7 éteint, on attend

LDA #44           ; 44+256=300 

_LOOP2

CMP $D012         ; Compare avec le registre D012

BCS _LOOP2        ; SI $D012<=44 on attend.

RTS

 

Dans cette exemple la table fait 64 entrée mais on peut évidements choisir une table plus grande ou plus petite en fonction de l’effet désirée. On veillera seulement à ce que la taille de notre table soit en puissance de 2 (2,4,8,16,32,64 etc) pour en faciliter la gestion.

 

TEXTE FADE-IN FADE-OUT

Programme un peu plus complexe mais avec le même principe que le programme précédant : on utilisera la table de couleur que nous appliquerons aux cellules de texte. On démarre avec un écran de fond et de bord noir on efface l’écran et on positionne les couleurs de l’écran en noire.

On affiche un texte qui nous ferons progressivement apparaitre et disparaitre en changeant les couleurs de la cellule du texte.

 

Pour changer la couleur d’une cellule il nous faut changer la couleur des registres du VIC de $D800 a $D7EF. Ces 1000 emplacements correspondent à la couleur des 1000 cellules de la mémoire écran.

La formule pour trouver l’adresse du registre de couleur d’une cellule est la même que pour la mémoire écran ; Y*40+X+BASE où la BASE est égale a $D800 (55296).

Par simplicité le code ci-dessous n’agit que sur toute la ligne dans laquelle le texte est affiché.

 

 

*= $801

.BYTE $0B,08,$0A,$00,$9E,$32,$30,$36,$34,$00         ; BASIC 10 SYS2064

*= $810

START

; EFFACE L'ECRAN

      JSR $E544              

; SAUVE LES COULEURS COURANTE

      LDA $D020

      STA SAVEVIC

      LDA $D021

      STA SAVEVIC+1

      LDA $D800+8*40

      STA SAVEVIC+2

; ECRAN NOIRE

      LDA #$00

      STA $D020

      STA $D021

; ON COMMENCE PAR INITIALISER LES COULEUR DES CELLULES DE NOTRE TEXTE EN NOIRE

      TAX                     ; A=X=0

      JSR INITCOLORL8

; ON AFFICHE NOTRE TEXT QUI DOIT SE TERMINER PAR UN 0

      LDX #$00                ; X COMME INDEX

      LDA TEXT1               ; CHARGE DANS A le premier caractère de notre texte

LOOPTEXT

      ; POSITION DANS LA MEMOIRE ECRAN: Y=8 X=8 MEM= Y*40+X -> 320+8 =352 + 1024 (base) = 1376

      STA 8*40+1024+8,X       ; Afficher à l'écran le caractère en L=8 et C=8+index X

      INX                     ; Incrémente l'index

      LDA TEXT1,X             ; Caractère suivant

      BNE LOOPTEXT            ; Si diffèrent de 0 on boucle

                             ; Sinon on a fini

; EN CE MOMENT NOTRE TEXT EST INVISIBLE CAR LA COULEUR DES CELLULE EST EN NOIR

      LDX #$00

MAIN

; ON CHANGE PROGRESSOVEMENT LES COULEUR

      JSR VSYNC1        ; SYNCHRONISATION ATTENTE QUE LA LIGNE 251 SOIT GENEREE

; JSR VSYNC1      ; On rajoutera des appels a VSYNC1 pour ralentir l’effet.

      ; CHANGEMENT DE COULEUR X INDEX COURANT

LDA COLORTAB,X    ; CHARGE LA COULEUR DE LA TABLE

JSR INITCOLORL8   ; APPLIQUE

INX               ; INCREMENTE INDEX

TXA               ; INDEX DANS A

AND #$3F          ; A&63 pour 0<=A<=63

TAX               ; INDEX DANS X

; ON ATTEND QU'UNE TOUCHE BREAK OU SPACE SOIT APPUYER

WAITBRK

      LDA $DC01        

      CMP #$FF         

      BEQ MAIN

; QUITTE ET RESTAURE LA COULEUR ET L’ETAT INITIAL DU VIC

      BRK

TEXT1

      .BYTE "PREMIERE INTRO C-64 !"      ; Le texte que nous afficherons

      .BYTE $00                          ; Doit se terminer par 0

 

SAVEVIC

      .BYTE 0,0,0

; TABLE DE 64 COULEURS FADE TO WHITE FADE TO BLACK

COLORTAB

      .BYTE 0,0,0,0                ;4    NOIRE

      .BYTE 11,11,11,11            ;8    GRIS FRONCE

      .BYTE 12,12,12,12            ;12   GRIS MOYEN

      .BYTE 15,15,15,15            ;16   GRIS CLAIRE

      .BYTE 1,1,1,1                ;20   BLANC

      .BYTE 1,1,1,1                ;24

      .BYTE 1,1,1,1                ;28

      .BYTE 1,1,1,1                ;32

      .BYTE 1,1,1,1                ;38

      .BYTE 15,15,15,15            ;40

      .BYTE 12,12,12,12            ;44

      .BYTE 11,11,11,11                  ;48

      .BYTE 0,0,0,0                ;52

      .BYTE 0,0,0,0                ;56

      .BYTE 0,0,0,0                ;60

      .BYTE 0,0,0,0                ;64

; PAR SIMPLICITE ON AFFECTE TOUTE LA LIGNE

; A = COULEUR A APPLIQUER

; REGISTRE AFFECTE : Y ET SR

INITCL8

      LDY #$00

_LOOP

      STA 8*40+$D800,Y

      INY

      CPY #40

      BNE _LOOP

RTS

; SYNCRO IMAGE DU FOND

VSYNC1

LDA #$FB          ; 251

_LOOP

CMP $D012         ; Compare avec le registre D011

BCS _LOOP         ; SI $D012<=251 on attend.

RTS

           

 

RASTERBARS

Pour afficher une ligne de RASTER, on va surveiller après avoir désactivé l’écran, le registre $D012 pour changer la couleur entre deux position.

 

Le principe de Rasterbar est, après avoir désactivé l’écran de fond, de surveiller sur quelle ligne balaie le canon électron et changer, à un moment de notre choix et avec une valeur de notre choix, le registre $D020.

Pour ce faire on surveille l’état du registre $D012 qui indique la position vertical du balayage et lorsque celle-ci atteint la valeur désirée on change immédiatement la couleur du registre $D020. 

Il faut le faire très vite car nous n’avons pas beaucoup de temps. Les couleurs seront contenues dans une table comme pour les programmes texte fade-in/fade-out vu précédemment.

 

SimpleRasterBar :

 

*= $801

.BYTE $0B,08,$0A,$00,$9E,$32,$30,$36,$34,$00         ; BASIC 10 SYS2064

*= $810

START

      SEI                                ; DESACTIVE LES INTERRUPTIONS

      LDX #$00                          

      STX $D011                          ; DESACTIVE L’ECRAN DE FOND

MAIN

      LDY #$80                           ; NOTRE RASTERBAR DEMMARRE EN LIGNE 128

      LDX #$00                           ; X comme index de couleur a 0

      STX $D020                          ; Ecran NOIR

_LOOP

      LDA BARCOL,X                       ; COULEUR DANS A

_@1:

      CPY $D012                          ; COMPARE Y avec la ligne courante

      BNE _@1                            ; SI DIFFERENT ON ATTEND

      ; OK NOUS SOMMES SUR LA BONNE LIGNE

      STA $D020                          ; APPLIQUE LA COULEUR

      CPX #31                            ; 31 Lignes

      BEQ MAIN                           ; X=31 Nous avons fini notre RASTERBAR

                                         ; ON REDEMARRE DEPUIS LE DEBUT

      INX                                ; SINON ON INCREMENTE X index pour la prochaine couleur

      INY                                ; INCREMENTE Y la ligne suivante

      JMP _LOOP                          ; ET BOUCLE

; LES COULEUR DE NOTRE RASTERBAR

; TABLEAU DE 32 ENTREES

BARCOL

      .BYTE $06,$0E,$06,$0E             

.BYTE $06,$0E,$06,$0E             

.BYTE $03,$0E,$03,$0E             

      .BYTE $03,$01,$03,$01             

      .BYTE $03,$01,$03,$01             

      .BYTE $03,$0E,$03,$0E             

.BYTE $06,$0E,$06,$0E             

      .BYTE $06,$0E,$00,$00             

 

    

Même si le programme est simple son fonctionnement n’est pas aussi évident. La première chose est bien évidement lorsque nous somme sur la bonne ligne nous devons immédiatement appliquer la couleur et nous n’avons que 4 cycles de disponible. Si nous dépassons cette limite la ligne d’overscan commence à s’afficher avant le changement de couleur ce qui provoquera un tremblement du bord gauche. La deuxième contrainte et qu’il faut terminer notre dernière ligne par la même couleur que celle du fond.

Avant de s’amuser à animer notre « rasterbar » gardons nos bonne habitudes ajoutons la possibilité de pourvoir quitter le programme proprement.

*= $801

.BYTE $0B,08,$0A,$00,$9E,$32,$30,$36,$34,$00         ; BASIC 10 SYS2064

*= $810

START

      ; MEMORISE L'ETAT DU VIC POUR CORRECTEMENT LE RESTAURER

      LDX   $D011

      STX SAVEVIC             ; SAUVE $D011

      LDX $D020

      STX SAVEVIC+1           ; SAUVE $D020

      ; INITIALISATION

      SEI                     ; DESACTIVE LES INTERRUPTIONS

      LDX #$00                          

      STX $D011               ; DESACTIVE L’ECRAN DE FOND

MAIN

      LDY #$80                ; NOTRE RASTERBAR DEMMARRE EN LIGNE 128

      LDX #$00                ; X comme index de couleur a 0

      STX $D020               ; Ecran NOIR

_LOOP

      LDA BARCOL,X            ; COULEUR DANS A

_@1:

      CPY $D012               ; COMPARE Y avec la ligne courante

      BNE .@1                 ; SI DIFFERENT ON ATTEND

      ; OK NOUS SOMMES SUR LA BONNE LIGNE

      STA $D020               ; APPLIQUE LA COULEUR

      CPX #31                 ; 31 Lignes

      BEQ _SUITE              ; X=31 Nous avons fini notre RASTERBAR                                

                             ; ON REDEMARRE DEPUIS LE DEBUT

      INX                     ; SINON ON INCREMENTE X index pour la prochaine couleur

      INY                     ; INCREMENTE Y pour la ligne suivante

      JMP _LOOP               ; ET BOUCLE

_SUITE

; TOUCHE POUR FIN DU PROG ?

      LDA $DC01               ; Lecture du CIA-1     

      CMP #$FF                ; TOUCHE SPACE, RUN/STOP, Q,?

      BNE _END                ; OUI ON QUITTE

      JMP MAIN

; Si vous utiliser un monitor laissez un peu de place ici.

; Disons une quarantaine d’octet.

_END

      ; QUITTE ET RESTAURE LA COULEUR ET L’ETAT INITIAL DU VIC

      CLI                     ; RETABLIT LES INTERRUPTIONS

      BRK  

; LES COULEUR DE NOTRE RASTERBAR

BARCOL

      .BYTE $06,$0E,$06,$0E             

      .BYTE $06,$0E,$06,$0E        

      .BYTE $03,$0E,$03,$0E             

      .BYTE $03,$01,$03,$01             

      .BYTE $03,$01,$03,$01             

      .BYTE $03,$0E,$03,$0E             

      .BYTE $06,$0E,$06,$0E             

      .BYTE $06,$0E,$06,$00             

; PLACE POUR SAUVER L’ETAT DU VIC

SAVEVIC

      BYT $00,$00

ANIMATION DE NOTRE RASTERBAR PAR SELF-MODFYING:

Maintenant nous allons essayer d’animer notre Rasterbar. On va maintenant faire démarrer celle-ci en ligne $40 pour la faire descendre en ligne $D0. Puis la faire remonter en ligne $40 et ainsi de suite. Comment allons-nous y prendre ? Nous n’allons pas modifier le corps principal du programme en revanche nous allons utiliser une technique qu’on appelle le « self-modying » pour modifier le code du programme dynamiquement. Par exemple après le label MAIN, notre programme fixe la valeur de Y à $80 ; valeur à laquelle la rasterbar doit apparaitre. Lorsque nous aurons finis nous allons modifier l’instruction dynamiquement en incrémente le deuxième octet de l’instruction LDY #$80 c’est-à-dire le paramètre #val de LDY #val.

MAIN

      LDY #$40                ; NOTRE RASTERBAR DEMMARRE EN LIGNE 64

      LDX #$00                ; X comme index de couleur a 0

      STX $D020               ; Ecran NOIR

_LOOP

      LDA BARCOL,X            ; COULEUR DANS A

_@1

      CPY $D012               ; COMPARE Y avec la ligne courante

      BNE _@1                 ; SI DIFFERENT ON ATTEND

      ; OK NOUS SOMMES SUR LA BONNE LIGNE

      STA $D020               ; APPLIQUE LA COULEUR

      CPX #31                 ; 31 Lignes

      BEQ _SUITE              ; X=31 Nous avons fini notre RASTERBAR                                

                             ; ON REDEMARRE DEPUIS LE DEBUT

      INX                     ; SINON ON INCREMENTE X index pour la prochaine couleur

      INY                     ; INCREMENTE Y pour la ligne suivante

      JMP _LOOP               ; ET BOUCLE

_SUITE:

      INC MAIN+1              ; Incrémente le démarrage de notre Rasterbar !

      ……………

      JMP MAIN

Il suffit juste d’ajouter cette instruction et notre Rasterbar s’anime. Evidement lorsque la valeur de LDY #val atteint 0 les artefacts se produisent en haut de l’écran jusqu’à ce que la valeur $39 et le rasterbar recommence à descendre.

On peut aller plus loin dans notre jeu de modification du code dynamiquement en testant par exemple la nouvelle valeur #val de LDY #val et si il est supérieur a une certaine valeur on modifiera carrément l’instruction INC ($EE) en DEC ($CE) et vice-versa si cette valeur est supérieure.

_SUITE

      INC MAIN+1              ; Incrémente dynamiquement le démarrage de notre Rasterbar !

      LDA MAIN+1

      CMP #$A0

      BCS .MAX                ; Branche si A>$B0

      CMP #$3F

      BCC .MIN                ; Branche si A<=$3F

      JMP MAIN

_MAX                         ; NOTRE RASTER A DEPASSER $B0

      LDA #$CE                ; IL FAUT MAINTENANT QU’ELLE REMONTE L’ECRAN

      STA _SUITE              ; EN REMPLCANT INC MAIN+1 par DEC MAIN+1 (opcode $CE) !

      JMP MAIN

_MIN                         ; NOTRE RASTER BAR A ATTEIND LA VALEUR 3F ou moins

      LDA #$EE                ; IL FAUT MAINTENANT QU’ELLE DESCENDE L’ECRAN

      STA _SUITE              ; EN REMPLCANT DEC MAIN+1 par INC MAIN+1 (opcode $EE) !

      JMP MAIN

Le programme complet devient donc :

*= $801

.BYTE $0B,08,$0A,$00,$9E,$32,$30,$36,$34,$00         ; BASIC 10 SYS2064

*= $810

START

      ; MEMORISE L'ETAT DU VIC POUR CORRECTEMENT LE RESTAURER

      LDX   $D011

      STX SAVEVIC             ; SAUVE $D011

      LDX $D020

      STX SAVEVIC+1           ; SAUVE $D020

      ; INITIALISATION

      SEI                     ; DESACTIVE LES INTERRUPTIONS

      LDX #$00                          

      STX $D011               ; DESACTIVE L’ECRAN DE FOND

MAIN

      LDY #$40                ; NOTRE RASTERBAR DEMMARRE EN LIGNE 64

      LDX #$00                ; X comme index de couleur a 0

      STX $D020               ; Ecran NOIR

_LOOP

      LDA BARCOL,X            ; COULEUR DANS A

_@1

      CPY $D012               ; COMPARE Y avec la ligne courante

      BNE _@1                 ; SI DIFFERENT ON ATTEND

      ; OK NOUS SOMMES SUR LA BONNE LIGNE

      STA $D020               ; APPLIQUE LA COULEUR

      CPX #31                 ; 31 Lignes

      BEQ _SUITE              ; X=31 Nous avons fini notre RASTERBAR                                

                             ; ON REDEMARRE DEPUIS LE DEBUT

      INX                     ; SINON ON INCREMENTE X index pour la prochaine couleur

      INY                     ; INCREMENTE Y pour la ligne suivante

      JMP _LOOP               ; ET BOUCLE

_SUITE

; TOUCHE POUR FIN DU PROG ?

      LDA $DC01               ; Lecture du CIA-1     

      CMP #$FF                ; TOUCHE SPACE, RUN/STOP, Q ?

      BNE .END                ; OUI ON QUITTE

_SELF

      INC MAIN+1              ; Incrémente dynamiquement le démarrage de notre Rasterbar !

      LDA MAIN+1

      CMP #$D0

      BCS .MAX                ; Branche si A>$D0

      CMP #$3F

      BCC .MIN                ; Branche si A<=$3F

      JMP MAIN

_MAX:                        ; NOTRE RASTER A DEPASSER $B0

      LDA #$CE                ; IL FAUT MAINTENANT QU’ELLE REMONTE L’ECRAN

      STA _SELF               ; EN REMPLCANT INC MAIN+1 par DEC MAIN+1 (opcode $CE) !

      JMP MAIN

_MIN:                        ; NOTRE RASTER BAR A ATTEIND LA VALEUR 3F ou moins

      LDA #$EE                ; IL FAUT MAINTENANT QU’ELLE DESCENDE L’ECRAN

      STA _SELF               ; EN REMPLCANT DEC MAIN+1 par INC MAIN+1 (opcode $EE) !

      JMP MAIN

 

_END:

      ; QUITTE ET RESTAURE LA COULEUR ET L’ETAT INITIAL DU VIC

      CLI                     ; RETABLIT LES INTERRUPTIONS

      BRK                    

; LES COULEUR DE NOTRE RASTERBAR

BARCOL

      .BYTE $06,$0E,$06,$0E             

      .BYTE $06,$0E,$06,$0E             

      .BYTE $03,$0E,$03,$0E             

      .BYTE $03,$01,$03,$01             

      .BYTE $03,$01,$03,$01             

      .BYTE $03,$0E,$03,$0E             

      .BYTE $06,$0E,$06,$0E             

      .BYTE $06,$0E,$06,$00             

; PLACE POUR SAUVER L’ETAT DU VIC

SAVEVIC

      .BYTE $00,$00

 

 

Toute la puissance du self-modying est illustrée dans ce petit programme : en très peu (relativement) de lignes de codes supplémentaires nous avons réussi à animer notre rasterbar !

Le self-modying est un des aspects des plus fascinants de l’assembleur MOS65xx. Les avantages sont souvent un code plus court et plus rapide. Le désavantage est qu’elle altère la lisibilité du code c’est pourquoi il vaut mieux bien documenter tout « self-modying ».

Pour ma part je l’utilise systématiquement lorsque je manipule des adresses le MOS65xx ne possédant pas d’adressage indirect type LDA (abs).

 

Bon en réalité les RasterBars se programment plutôt à travers les interruptions mais c’est un très bonne exercice d’essayer de réaliser diverses effets de Raster Bar sans utiliser les interruptions.

Les rasters est un sujet très vaste, on y reviendra dans une autre partie mais je vous encourage à tenter des expériences par vous-même.

 

SCROLLING DE TEXTE

Nous savons afficher du texte maintenant si nous tentions de l’animer. 

Effet 5 :          Simple scroll Text

Commençons par afficher un texte quelconque avec le nombre de caractère à afficher connue. Sachant qu’une ligne contient 40 cellules on affichera 40 cellules.

            LDX #$00             ; Index a 0

LOOP

     LDA TEXT1,X          ; Caractère dans A

     STA 9*40+1024,X      ; Ecrit à l’écran sur une cellule de la 9eme ligne

     INX                  ; Caractère et cellule suivante

     CPX #40              ; index = 40 ?

     BNE LOOP             ; non on continue

     ;suite

TEXT1

.BYTE "EXEMPLE DE SCROLLING”

Etant donné que l’on tente d’afficher 40 caractères et que notre texte n’en contient que 20 caractères, les 20 cellules suivantes sont du bruit. Pour y remédier faisons en sorte que notre texte contienne 40 caractères en ajoutant des espaces :

.BYTE "EXEMPLE DE SCROLLING”

.BYTE "                   

    

Sans espace                                                                                       Avec 20 espaces après le texte

 

Plaçons le texte à droite en ajoutant des espaces avant

.BYT "                   

.BYT "EXEMPLE DE SCROLLING”

.BYT "                   

On obtient :   

Apres 20 espaces avant le texte.

 

Pour déplacer le texte et sachant que nous écrirons systématiquement sur tout la ligne, nous avons besoin de deux index : un index pour le texte et un index pour la cellule de la ligne.

On choisit par exemple le registre Y comme index de Text et X index de la cellule de la ligne.

LDX #$00

     LDY #$00

LOOPTEXT

     LDA TEXT1,Y

     STA 10*40+1024,X

     INX

     INY

     CPX #40

     BNE LOOPTEXT

 

Maintenant pour faire bouger le texte nous devons rajouter une boucle dans lequel on va incrémenter le départ du texte c’est-à-dire l’index Y : au lieu de réinitialiser à 0 on va l’initialiser par incrément de la valeur courante. Mais cette valeur courante doit-être stocker quelque part.

 

On peut se servir de la PILE 

LDA #$00                     ; INDEX DE TEXTE

PHA                          ; DANS LA PILE

LOOPSCRL   

      TAY                          ; INDEX DE TEXT DANS Y

LDX #$00

LOOPTEXT

      LDA TEXT1,Y                  ; LECTURE DU CARACTERE DU TEXT

      STA 10*40+1024,X

      INX

      INY                          ; CARACTERE SUIVANT

      CPX #40

      BNE LOOPTEXT

      PLA                          ; RECUPERE L’INDEX DE TEXTE

      CLC                          ; RETENUE A 0

      ADC #01                      ; QUE L’ON INCREMENTE

      PHA                          ; ET QUE L’ON REPLACE DANS LA PILE

      CMP #val                     ; VALEUR MAXIMALE DE L’INDEX DE TEXTE

      BNE LOOPSCRL                 ; TANT QU’IL DIFFERE ON BOUCLE

      PLA                          ; IMPERATIF POUR PRESERVER LE POINTEUR DE PILE

 

Ou bien avec une variable dans la mémoire.

LDY #$00

STY .CURY

LOOPSCRL:

      LDX #$00

LOOPTEXT:

      LDA TEXT1,Y

      STA 10*40+1024,X

      INX

      INY

      CPX #40

      BNE LOOPTEXT

      INC .CURY

      LDY .CURY

      CPY #val                     ; Compare a une valeur choisie

      BNE LOOPSCRL                 ; Tant que Index de la chaine diffèrent et diffèrent on continue.

CURY                                ; NOTRE VARIALBE DE POINTEUR DE TEXTE COURANT

.BYTE 0

 

Ou plus simplement par self-modying.

LDX #$00

LOOPSCRL:

      LDY #$00

LOOPTEXT:

      LDA TEXT1,Y

      STA 10*40+1024,X

      INX

      INY

      CPX #40

      BNE LOOPTEXT

      INC LOOPSCRL+1          ; Augmente la valeur d’initialisation de Y

      LDA #val                ; valeur pour comparer

      CMP LOOPSCRL+1          ; A-Courant

      BNE LOOPSCRL            ; Tant que diffèrent de 0 on continue.

 

Quel que soit la méthode choisie il faudra ne pas oublier d’attendre avant chaque début de .LOOPSCROLL pour rendre l’animation visible. L’idéal est de bien sur synchroniser avec le retour vertical.

Ci-dessous programme complet

 

*= $801

.BYTE $0B,08,$0A,$00,$9E,$32,$30,$36,$34,$00         ; BASIC 10 SYS2064

*= $810

START

      JSR $E544

      LDX #$00

      LDY #$00

      STY .CURY

LOOPSCRL

      JSR VSYNC1

LOOPTEXT

      LDA TEXT1,Y

      STA 10*40+1024,X

      INX

      INY

      CPX #40

      BNE LOOPTEXT

      ;SINON

      LDX #0

      INC .CURY

      LDY .CURY

      CPY #40

      BNE LOOPSCRL

      JSR $E544               ; ON EFFACE L'ECRAN

      RTS                     ; Et ON QUITTE

CURY

      .BYTE 0

TEXT1

      .TEXT "                    "

      .TEXT "EXEMPLE DE SCROLLING"

      .TEXT "                    "

; VSYNC1 qui rend la main en ligne 252 donc lorsque l’écran de fond a été généré.

VSYNC1 

      LDA #$FB          ; 251

_LOOP

CMP $D012         ; Compare avec le registre D011

      BCS _LOOP         ; SI $D012<=251 on attend.

      RTS

Sachez que cette technique simple de scrolling, c’est-à-dire l’affichage de toute une ligne en déplaçant seulement le pointeur de texte, est transposable sur quasiment toutes les plateformes. (Je l’ai, par exemple, récemment appliquée sans problème sur un petit afficheur LCD à 16 colonnes avec un microcontrôleur AVR) 

Effet 6 :          Smooth Scroll Text

Maintenant pour rendre l’animation fluide nous devons pouvoir déplacer notre texte par pixel et non par cellule (8 pixels). La capacité de Scrolling par pas de 8 pixels est une des possibilités du VIC.

Il faut d’abord configurer le bit 3 du registre $D016 a 0 pour configurer une ligne a 38 colonnes. Ensuite la valeur des bits b2, b1, b0 représentent le décalage en pixels vers la droite.

Les 4 premiers bits du registre $D016           b3 : 38/40 colonnes    b2, b1, b0=valeur du décalage en pixel à droite.

Remarque sur le registre $D016 : les bit 4 sélectionne ou non le mode multi-couleur que nous verrons plus tard. Le bit 5 n’a aucune effet sur la plupart des C-64 en revanche sur les premiers modèle, l’allume revient à stopper le VIC-II donc il faudra veiller à le laisser a 0. Les autres bits ne sont pas utilisés et on les laissera à 0.

 

Pour voir comment fonctionne le scrolling par pas de 8 pixels, essayons ce petit programme pour admirer quel effet très simple nous pouvons effectuer en jouant seulement sur le registre $D016.

 

*= $801

.BYTE $0B,08,$0A,$00,$9E,$32,$30,$36,$34,$00         ; BASIC 10 SYS2064

*= $810

START

      JSR $E544

            ; ECRAN NOIRE

      LDA #$00

      STA $D020

      STA $D021

; ON DESSINNE SUR LA DERNIERE LIGNE EN MODE TEXT UN CARACTERE GRAPHIQUE

      LDX #$00                ; X COMME INDEX

      LDA #91                 ; A contient 91 un caractere graphique

LOOPDRAW

      STA 24*40+1024,X        ; Afficher à la derniere ligne

      INX                     ; Incrémente l'index

      CPX #40

      BNE LOOPDRAW

; PREPARE LE SCROLLING

      LDA #$07                ; CSEL=0->scrolling horizontale

      STA $D016

      CLC                               

; BOUCLE PRINCIPALE

MAINLOOP

      JSR VSYNC3

      ;SCROOLING SUIVANT

      LDA $D016

      CLC                     ; CLEAR CARRY CAR NOUS ALLONS UTILISER L’INSTRUCTION ADC  

      ADC #$FF                ; + -1

      AND #$07

      STA $D016

      ;VERIFIE LES TOUCHES STOP/Q/Espace…

      LDA $DC01        

      CMP #$FF         

      BEQ MAINLOOP

      ; UNE INSTRUCTION BRK SUFFIT POUR RETABLIR L’ETAT D’AVANT PROGRAMME

      BRK

; SYNCRONISATION VERTICAL

[BLOCK]

VSYNC3 

BIT $D011         ; B7 DANS N

BMI VSYNC3        ; B7 Allumée on attend

LOOP

BIT $D011         ; B7 DANS N

BPL LOOP          ; B7 éteint, on attend

LDA #44           ; 44+256=300 

LOOP2

CMP $D012         ; Compare avec le registre D012

BCS LOOP2         ; SI $D012<=44 on attend.

RTS

[BEND]

 

 

 

Donc pour le déplacement du texte de gauche vers la droite il faut démarrer avec un scroll à 7 et le diminuer dans une boucle. Une fois la valeur 0 atteinte, on doit le placer à 7 et on affiche le texte avec l’index incrémenter comme précédemment.

 

; SROLL X SMOOTH <- $D016&07 démarre a 7 que l’on décrémente dans la boucle SMOOTHXP

SMOOTHXP

      JSR SYNCHVERT

      DEC $D016

      LDA $D016

      AND #$07

      BEQ END           ; LORSQUE $D016 ATTEINT 0, ON PEUT REPRENDRE LE SCROLL NORMAL.

      JMP SMOOTHXP

END

      JSR SYNCVERT

      LDA $D016

      ORA #$07

      STA $D016

 

Donc après avoir affiché on déplace par pas de pixels avec la fonction ci-dessous et ensuite on passe à l’index Y suivant et on boucle. La synchronisation verticale se fait dans SMOOTHXP

*= $1000

START:

; INIT CSEL $D016

      LDA $D016

      STA SAVEVIC       ; Sauve le registre $d016

      AND #$F0          ; Eteint les b3-b0

      ORA #$07          ; Scroll pas a 7

      STA $D016         ; Applique

; INIT Y

LDY #$00

STY CURY

LOOPSCRL:

      LDX #$00

LOOPTEXT:

      LDA TEXT1,Y

      STA 10*40+1024,X

      INX

      INY

      CPX #40           ; On affiche toujours 40 cellules même si 38 apparaissent.

      BNE LOOPTEXT

;****** SMOOTH SCROLL HORIZONTALE

SMOOTHXP:

      JSR SYNCHVERT

      DEC $D016

      LDA $D016

      AND #$07

      BEQ ENDSXP

      BNE SMOOTHXP

ENDSXP:

      JSR SYNCVERT

      LDA $D016

      ORA #$07

      STA $D016

;***** END SMOOTH SCROLL

      INC .CURY

      LDY .CURY

      CPY #40                      ; Compare a une valeur choisie

      BNE LOOPSCRL                 ; Tant que Index de la chaine diffère, on continue.

END:

      ;etc

      LDA .SAVEVIC

      STA $D016

      RTS                          ; On quitte le programme

CURY       

.BYT  0

SAVEVIC

      .BYT 0

TEXT1

      .BYT "                    "        ; 20 colonnes

      .BYT "                    "        ; 20 colonnes

      .BYT "EXEMPLE DE SCROLLING"

      .BYT "                    

 

 

LECTURE DE FICHIER SID

Bon on sait faire pas mal de chose. Et si nous ajoutions un peu de musique ?

Si la création de « SID players » est complexe, ils sont, en revanche, très facile à utiliser. Il suffit juste d’appeler leur routines « play » continuellement après par exemple une synchronisation vertical (ou dans une interruption). La plupart des fichiers SID se chargent à partir de l’adresse $1000. La routine INIT est souvent en $1000 et PLAY en $1003.

*= $0810

START:

      JSR LOADSID ; CHARGEMENT DU FICHIER

      BNE .END          ; SI ECHEC ON QUITTE

; INIT SID FILE

      LDA #$00

      JSR $1000

; PLAY SID

LOOP

      JSR $1003

      JSR SYNCVERT

; KEY FOR QUIT

LDA $DC01

      CMP #$FF

      BEQ .LOOP

END:

      LDA #$00

      STA $D418         ; TURN OFF SID

      RTS

; CHARGEMENT D’UN FICHIER SID EN MEMOIRE

LOADSID

;SETUP DEVICE 8

LDA #$01          ; FILE 1

LDX #$08          ; DEVICE 8

LDY #$00          ; CHANNEL 0

JSR $FFBA         ; SETLFS

;CALCULATE STRING LENGTH

LDX #$00

_LOOP:

LDA SIDNAME,X     ; READ NEXT CHAR

BEQ END                 ; IF 0 END

INX                     ; ELSE X+=1

BNE _LOOP               ; LOOP

; SET NAME

TXA                     ; X LENGTH OF FILE NAME DANS A

      LDX #SIDNAME            ; X -> LOW FILENAME POINTER

      LDY #>SIDNAME           ; Y -> HIGH FILENAME POINTER

      JSR $FFBD               ; SETNAME

; LOAD FILE

      LDA #$00                ; A=0 LOAD

      LDX #$00                ; LOW ADDRESS

      LDY #$00                ; HIGH ADDRESS   

      JSR $FFD5               ; LOAD FILE

      RTS

SIDNAME

      .TEXT "SUPREMACY.DAT"

      .BYTE 0

; VSYNC1 qui rend la main en ligne 252 donc lorsque l’écran de fond a été généré.

VSYNC1 

      LDA #$FB          ; 251

_LOOP

CMP $D012         ; Compare avec le registre D011

      BCS _LOOP         ; SI $D012<=251 on attend.

      RTS

 

 

IMAGES BITMAP

Par default, le C-64 démarre en mode Text où 1000 emplacements de la mémoire écran (par default en $0400) affichent l’un des 256 caractères qui se trouve dans la ROM  (ou la RAM nous y reviendrons).

Mais pour afficher des images plus précises, le C-64 dispose du mode Bitmap ou chaque pixel sera contrôlé par 1 bit d’un octet. Une image bitmap occupe 8000 octets dans la mémoire sans compter les 1000 emplacements de la mémoire écran qui va contrôler les couleurs. L’organisation mémoire d’un bitmap est complexe. Pourtant grâce à des outils comme Timanthes, il est facile de créer des images et ensuite de les faire afficher sur notre C-64.

Pour passer en mode Bitmap il faut allumée le bit 5 du registre $D011 du VIC. Les deux modes officiels du bitmap sont simple couleur et multi couleur. Par default l’image bitmap à afficher commence en $0000 mais on devra le placer en $2000 car en plus de la page 0 et de la pile, dans la zone située en $1000-$1FFF,  le VIC n’y voit que la ROM de caractères.

; C64 TEST VIC DIVERS

; TEST BITMAP

; EVIDENCE QUE LE VIC NE VOIT QUE LA ROM EN $1000-$1FFF

ORG $0801

      BYT $0B,$08,$0A,$00,$9E

BYT $32,$30,$36,$34,$00 ;BASIC 10 SYS2064

ORG $0810

START:

;MODE BITMAP 1

      LDA $D011

      STA SAVEVIC11

      ORA #$20    ; bit5 1 mode bitmap

      STA $D011   ; apply

.LOOP1:

      LDA $DC01

      CMP #$FF

      BEQ .LOOP1

.END:

      LDA #$1B

      STA $D011

      BRK

SAVEVIC11:

      BYT $00,$00                                                     

TRADINTRO_I_BM_01         

Pour placer le bitmap en $2000, il faut allume le bit 3 du registre $D018.

Simple color

En simple couleur, la résolution est de 320x200. L’écran est toujours divisé en cellule de 8x8 pixels en 25 rangées et 40 colonnes. Chaque cellule contient 8 octets ou le premier octet contrôle 8 pixels adjacent de la ligne la plus haute et le huitième octet la ligne la plus basse dans la cellule.

La formule pour trouver l’adresse de l’octet de notre pixel est :

            (Y*8/8)*40 + X/8*8 =>         X&F8 * 40 + X&F8

Il faut évidemment ajouter l’adresse de départ de notre Bitmap.

Oui c’est assez complexe, quelques exemples seront plus parlants. Si vraiment vous n’avez pas la tête pour ça sautez cette partie et allez directement à la lecture d’un fichier généré par Timanthes

Pixel 0,0          Adresse : $0000  Valeur de l’octet : $80

Pixel 1,0          Adresse : $0000 Valeur de l’octet : $40

Pixel 0,1          Adresse : $0001 Valeur de l’octet : $80

Pixel 8,0          Adresse : $0008 Valeur de l’octet : $80

Pixel 9,0          Adresse : $0008 Valeur de l’octet : $40

Pixel 8,8          Adresse  40*8+8 = $0148  Valeur de l’octet : $80

Pixel 128,0      Adresse = 128/8*8

Pixel 128,128

 

Pour activer le mode Bitmap il faut allume le bit 5 du registre $D011.

Le bit 4 du registre $D016 sélectionne ou non le mode Multi-color (MC)

Enfin le plus important est de définir l’adresse du bitmap. Une image bitmap peut être soit en 0 soit en $2000 par rapport à la base du VIC (voir les polices de caractères personnalisées).

Le bit 3 du registre $D018 va contrôler l’adresse du Bitmap. Celui-ci est en $2000 si b3 est allumée sinon en 0. Etant donné que la plage $1000-$1FFF est exclusivement vue par le VIC comme les bitmaps des polices de caractères en ROM on utilisera le plus souvent le Bitmap en $2000 (pour les banks 0 et 2).

 

; MODE BITMAP 1

      lda $D011

      ora #$20    ; bit5 1 mode bitmap

      sta $D011   ; apply

; MODE SINGLE COLOR

      lda $D016

      and #$EF    ;bit 4 0 Single color

      sta $D016

; BITMAP ADRESSE

      lda $D018   ; READ VIC CONTROL REGISTER

      ora #$08    ; b3=1 => $2000

      sta $D018   ; VIC Control register

 

Bitmap = 8000 octets soit $1F40 (4096+15*256+4*16=4096+3840+64)

            Editeur Timanthes :

                        http://csdb.dk/release/?id=30789

Cet éditeur nous permet de convertir avec plus ou moins de facilité une image pour le C-64. Une fois l’image convertis on sauve sous un format .prg que l’on va insérer dans la mémoire du C-64.

Attention, il semblerait que Timanthe n’exporte correctement que les images 320x200. Donc si vous voulez gênerez une image plus petite, exporter 320x200 en prenait que les parties qui vous intéresse.

Nous ne verrons que 2 modes : le mode bitmap simple couleur et le mode multi-couleur.

 

Pour bien convertir une image je vous propose cette manipulation sous Timanthes.

 

Prenez une image de votre choix fait un copier/coller dans l’éditeur.

Si l’image est trop sombre je vous conseille un auto-adjust.

Allez dans « effect » et « C-64 color ramp ». Jouez avec les différents paramètres jusqu’à ce que vous obteniez ce que vous désirez. On ferme en cliquant OK.

Ensuite allez dans layer properties et sélectionner index color et fix crash. Ensuite choisissez entre Hires Single Color et Hires Multi Color.

Une fois finit cliquer sur File -> Export pour sauver votre image.

 

Un fichier généré par Timanthes s’organise de cette façon:

$0000 $0001  Adresse de chargement de l’image en général contient la valeur $2000. Donc si nous faisons avec le BASIC un LOAD «nomimage.prg »,8 de l’image celle-ci sera chargé en $2000.

Une fois chargé, la mémoire devrait contenir :

$2000 $3F3F  Image bitmap

$4000-$43FF  couleur screen.

Donc il nous faut copier les informations des couleurs dans la mémoire écran (screen memory) de cette façon :

; Copie des infos couleur dans la mémoire écran

COPYSCREENCOLOR:

      LDX #$00

.LOOP:

      LDA $4000,X

      STA $0400,X

      LDA $4100,X

      STA $0500,X

      LDA $4200,X

      STA $0600,X

      LDA $4300,X

      STA $0700,X

      INX

      BNE .LOOP

      RTS

           

Ci-dessous un exemple d’un programme qui affiche un fichier Timanthes 320x200 en mode «Simple Color ».

Celui-ci est insérée dans le programme mais si vous utilisez TASM sur C-64 il faudra changez le programme pour d’abord charger l’image.

 

org $0801

      byt $0B,08,$0A,$00,$9E,$32,$30,$36,$34,$00           ; BASIC 10 SYS2064

org $0810

Start:

; INIT COLOR

      JSR COPYSCREENCOLOR

      JSR COPYVICCOLOR

; INIT VIC 

      ldx #$00 

      stx $D021

      stx $D020        

; MODE BITMAP 1

      lda $D011

      ora #$20    ; bit5 1 mode bitmap

      sta $D011  

; MODE MULTICOLOR

      lda $D016

      and #$EF    ; bit 4 0 singlecolor

      sta $D016

; BITMAP ADRESSE

      lda $D018   ; READ VIC CONTROL REGISTER

      ora #$08    ; b3=1 => $2000

      sta $D018   ; To VIC Control register

; Attente d'une touche pour quitter

.@1:

      Jsr $FF9F         ; SCAN KEY

      jsr $FFE4         ; GETIN CHAR

      beq .@1           ; IF = 0 THEN .@1

End:

; RESTORE VIC

      lda $D011

      and #$DF    ; bit5=0 --> mode TEXT

      sta $D011  

      ; MODE SINGLE COLOR

      lda $D016

      and #$EF    ; bit 4 0 restore

      sta $D016

      ; Screen Memory en BASE+ $400 (default)

      lda $D018

      and #$F7    ; b3=0 => $0000

      sta $D018   ; APPLY

      jsr $E544   ; CLEAR SCREEN

      ldx #$FE    ; Defaut overscan

      stx $D020   ; Overscan

      ldx #$F6    ; Defaut cadre

      stx $D021   ; Cadre

      rts

; Copie des infos couleur dans la mémoire écran

COPYSCREENCOLOR:

      LDX #$00

.LOOP:

      LDA $4000,X

      STA $0400,X

      LDA $4100,X

      STA $0500,X

      LDA $4200,X

      STA $0600,X

      LDA $4300,X

      STA $0700,X

      INX

      BNE .LOOP

      RTS

ORG $2000-2

INCBIN "MYC64IMAGE\\Maradona1SC"

 

 

Multi Color

; MODE BITMAP 1

      lda $D011

      ora #$20    ; bit5 1 mode bitmap

      sta $D011   ; apply

; MOD MULTICOLOR

      lda $D016

      ora #$10    ; bit 4 1 multicolor

      sta $D016

; BITMAP ADRESSE

      lda $D018   ; READ VIC CONTROL REGISTER

      ora #$08    ; b3=1 => $2000

      sta $D018   ; VIC Control register

En mode multi-couleur, un pixel est représenté sur 2 bits. (La résolution horizontale passe à 160)

00 couleur de fond

01 couleur screen memory 0

10 couleur screen memory 1

11 couleur vic memory

 

En mode multi couleur, l’organisation du fichier prg généré par Timanthes diffère par rapport au mode simple couleur devenant très bizarre.

Le fichier une fois charger devient :

$2000 $3F3F  Image bitmap

$3F40 $4327  Color Screen

$4270              Color Fond

$4328 $4727  Color VIC

 

Ci-dessous un exemple d’un Bitmap multicouleur

; Bitmap multicolor exemple

org $0801

      byt $0B,08,$0A,$00,$9E,$32,$30,$36,$34,$00           ; BASIC 10 SYS2064

org $0810

Start:

; INIT COLOR

      JSR COPYSCREENCOLOR

      JSR COPYVICCOLOR

; INIT VIC 

      ldx #$00 

      stx $D021

      stx $D020        

; MODE BITMAP 1

      lda $D011

      ora #$20    ; bit5 1 mode bitmap

      sta $D011  

; MODE MULTICOLOR

      lda $D016

      ora #$10    ; bit 4 1 multicolor

      sta $D016

; BITMAP ADRESSE

      lda $D018   ; READ VIC CONTROL REGISTER

      ora #$08    ; b3=1 => $2000

      sta $D018   ; To VIC Control register

; Attente d'une touche pour quitter

.@1:

      jsr   $FF9F       ; SCAN KEY

      jsr $FFE4         ; GETIN CHAR

      beq   .@1         ; IF = 0 THEN .@1

End:

; RESTORE VIC

      lda $D011

      and #$DF    ; bit5=0 --> mode TEXT

      sta $D011  

      ; MODE SINGLE COLOR

      lda $D016

      and #$EF    ; bit 4 0 restore

      sta $D016

      ; Screen Memory en BASE+ $400 (default)

      lda $D018

      and #$F7    ; b3=0 => $0000

      sta $D018   ; APPLY

      jsr $E544   ; CLEAR SCREEN

      ldx #$FE    ; Defaut overscan

      stx $D020   ; Overscan

      ldx #$F6    ; Defaut cadre

      stx $D021   ; Cadre

      rts

; Copie les couleurs de l’image dans la screen memory

COPYSCREENCOLOR:

      LDX #$00

.LOOP:

      LDA $3F40,X

      STA $0400,X

      LDA $4040,X

      STA $0500,X

      LDA $4140,X

      STA $0600,X

      LDA $4240,X

      STA $0700,X

      INX

      BNE .LOOP

      RTS

; Copie les couleurs de l’image dans les registres de couleurs

COPYVICCOLOR:

      LDX #$00

.LOOP:

      LDA $4328,X

      STA $D800,X

      LDA $4428,X

      STA $D900,X

      LDA $4528,X

      STA $DA00,X

      LDA $4628,X

      STA $DB00,X

      INX

      BNE .LOOP

      RTS

org $2000-2

insert "MYC64IMAGE\\vermeer.prg"

 

DIVISION D’ECRAN ET PREMIER PETIT CRACKTRO

 

En surveillant la ligne horizontale courante, il est possible de configurer l’écran pour avoir simultanément plusieurs modes.

 

Bien que nous n’ayons pas encore vu quelque notions plus techniques (configuration mémoire et interruptions) qui nous aurait facilité la tâche, nous sommes quand même en mesures d’écrire une petite «Intro» avec une image bitmap, une musique et un scrolling de texte. Les lignes 0 à 183 contiendront une image bitmap et les lignes 192 à 200 contiendrons le texte qui défilera en scrolling.

 

C’est beaucoup plus simple à réaliser qu’il n’y parait on reprend le programme qui affiche un Bitmap (Simple ou multi) et on va surveiller, comme pour un rasterbar, que l’on soit dans une ligne particulière pour basculer en mode texte. Ensuite on utilise la fonction VSYNC1 pour attendre que l’écran du fond ait fini d’être afficher pour repasser en mode bitmap et on boucle ainsi de suite.

Il nous faudra juste après avoir chargé notre bitmap initialiser les lignes texte 23 et 24 ainsi que leur couleur. On peut ensuite soit écrire le texte a afficher avant notre boucle main (si le texte ne s’animera pas) ou bien après avoir basculer en mode bitmap sachant que l’on disposera, entre le temps où l’on passera en bitmap et le moment où il faut surveiller notre lignes, d’au moins 13000 cycles en réserve (je n’ai pas fait le calcul exacte mais la réalité se rapprocherez plus de 13500 cycles 234*63 – (234/8 *40)) c’est largement suffisant pour afficher, animer et jouer de la musique.

Rappelons-nous qu’en mode PAL l’écran démarre à la ligne en RASTER 50 et donc attendre la ligne visuelle 184 correspond à attendre le RASTER 234.

 

Ci-dessous une simple division d’écran ce sera le corps de notre cracktro.

 

; C64 TUTO SPLIT SCREEN 0

; DIVISION D'ECRAN SANS UTILISER D'INTERRUPTION

; LIGNE 0-183     BITMAP MC

; LIGNE 184-199 TEXTE

ORG $0801

      BYT $0B,08,$0A,$00,$9E,$32,$30,$36,$34,$00           ; BASIC 10 SYS2064

ORG $0810

START:

;INIT COLOR IMAGE

      JSR COPYSCREENCOLOR

      JSR COPYVICCOLOR

; EFFACE LES COLONNES 23/24 et ecrit le texte dans la 24 colonne et initialise les couleurs

      LDX #$00                ; Index a 0

.LOOP1:

      LDA #$20                ; Espace pour effacer

      STA 23*40+1024,X        ; Ecrit à l’écran sur une cellule de la 23eme ligne

      LDA TEXT1,X             ; NOTRE TEXTE A AFFICHER

      STA 24*40+1024,X        ; Ecrit à l’écran sur une cellule de la 24eme ligne

      LDA #$01                ; Couleur blanche

      STA 23*40+$D800,X       ; Couleur de la 23eme colonne

      STA 24*40+$D800,X       ; Couleur de la 24eme colonne

      INX                     ; Caractère et cellule suivante

      CPX #40                 ; index = 40 ?

      BNE .LOOP1             ; non on continue

;INIT VIC

      LDX #$00                ; NOIRE

      STX $D020               ; POUR L’OVERSCAN

      LDA $4270               ; COULEUR DE FOND DE NOTRE IMAGE

      STA $D021               ; FOND

; AUTRE INITIALISATION ICI

      ;………………

      SEI                     ; DESACTIVE LES INTERRUPTIONS

MAIN:

; AVANT DE DEMARRER SOYONS SUR QUE NOUS SOYONS DANS UN RETOUR VERTICAL

LDY #251

.WAIT251:

      CPY $D012         ;LIGNE 251 ?

      BNE .WAIT251      ;NON ON ATTEND

      ;MODE BITMAP 1

      LDA $D011

      ORA #$20    ; bit5 1 mode bitmap

      STA $D011   ; apply

      ;MOD MULTICOLOR

      LDA $D016

      ORA #$10    ; bit 4 1 multicolor

      STA $D016

      ;BITMAP ADRESSE

      LDA $D018   ; READ VIC CONTROL REGISTER

      ORA #$08    ; b3=1 => $2000

      STA $D018   ; VIC Control register

; Au moins 13000 cyles disponible ici

      ;…………………

; DIVISION BITMAP -> TEXT

      LDY #234

.WAIT234:

      CPY $D012         ; ligne 234 ?

      BNE .WAIT234      ; non on attends

; PASSE EN MODE TEXT

      LDA $D011

      AND #$DF    ; bit5=0 --> mode TEXT

      STA $D011   ; apply

      ;MODE SINGLE COLOR

      lda $D016

      and #$EF    ; bit 4 0 restore

      sta $D016

      ;Screen Memory par default BASE=$0000 + $400

      lda $D018

      and #$F7    ; b3=0 => $0000

      sta $D018   ; APPLY

; TOUCHE STOP/ESPACE POUR QUITTER

      LDA $DC01

      CMP #$FF

      BEQ MAIN   

END:

      ;RESTORE VIC

      LDA $D011

      AND #$DF    ; bit5=0 --> mode TEXT

      STA $D011   ; apply

      ;MOD SINGLE COLOR

      LDA $D016

      AND #$EF    ; bit 4 0 restore

      STA $D016

      ;Screen Memory en par defaut BASE+ $400

      LDA $D018

      AND #$F7    ; b3=0 => $0000

      STA $D018   ; APPLY

      JSR $E544   ; CLEAR SCREEN

      LDX #$FE    ; Defaut overscan

      STX $D020   ; Overscan

      LDX #$F6    ; Defaut cadre

STX $D021   ; Cadre

      CLI         ; Reactive les interruptions

      RTS         ; Fin du programme

COPYSCREENCOLOR:

      LDX #$00

.LOOP:

      LDA $3F40,X

      STA $0400,X

      LDA $4040,X

      STA $0500,X

      LDA $4140,X

      STA $0600,X

      LDA $4240,X

      STA $0700,X

      INX

      BNE .LOOP

      RTS

COPYVICCOLOR:

      LDX #$00

.LOOP:

      LDA $4328,X

      STA $D800,X

      LDA $4428,X

      STA $D900,X

      LDA $4528,X

      STA $DA00,X

      LDA $4628,X

      STA $DB00,X

      INX

      BNE .LOOP

      RTS

TEXT1:

      byt "        EXEMPLE DE DIVISION D'ECRAN       "     ; 40 cellules

org $2000-2

      insert "MYC64IMAGE\\vermeer.prg"

 

 

Nous rajouterons du code dans les sections suivantes :

; AUTRE INITIALISATION ICI

            ;…………………

; AU MOINS 13000 CYCLES DISPONIBLE ICI

      ;…………………

 

Rajoutons de la musique. Il suffit d’insérer un SID file et de rajouter les lignes suivante :

 ; AUTRE INITIALISATION ICI

      ;SID FILE

      LDA #$00

      JSR $1000

            ;…………………

 

; AU MOINS 13000 CYCLES DISPONIBLE ICI

      JSR $1003

      ;…………………

 

Et on n’oublie pas de charger notre SID avant ou bien simplement en l’insérant dans notre programme à la fin du listing.

org $1000-2

      insert "LOADING.DAT"    ; UN FICHIER SID de moins de 4KO en $1000

 

Scrollons maintenant le texte. Cela ne devrait poser aucuns problèmes. Mais étant donné que nous avons désactivé les interruptions, le texte défilera trop rapidement et il sera difficile de le lire.

On utilisera donc directement le smooth scrolling mais il ne faudra l’appliquer que pour les cellules du texte et non notre Bitmap. On utilisera donc une variable pour sauver notre « scorllX » courant.

On appliquera ce dernier seulement lorsque nous passons en mode Texte.

Ci-dessous un extrait du corps de notre programme avec les modifications en bleu et les parties non modifie en noire et petit caractère.

 

; AUTRE INITIALISATION ICI

       ;………………

       LDA #$00

      STA CURYS

       JSR $1000           ; INIT SID FILE           

; SMOOTH X SCROLL INIT

      ; INIT CSEL $D016

      LDA $D016

      AND #$F0          ; Eteint les b3-b0

      ORA #$07          ; Scroll pas a 7

      STA $D016         ; Applique

      STA SMOOTHVAL

      SEI                 ; DESACTIVE LES INTERRUPTIONS

MAIN:

       ;ETC

; Au moins 18000 cyles disponible ici

       ;…………………

       ;PLAY SID

       JSR $1003

      ;SCROOL TEXT

.SCROLLT:

      LDA SMOOTHVAL           ; LECTURE DU SMOOTH X

      AND #$07                ; SEUL LES 3 DERNIERS BITS NOUS INTERESSE

      BEQ .BIGSCROLL          ; SI 0 ON PASSE AU BIGSCROLL

      BNE .SMOOTHSCROLL       ; SINON ON EFFECTUE JUSTE LE SMOOTHSCROLL

.BIGSCROLL:

      LDX #$00                ; INDEX A 0

      LDY CURYS

.LOOP1:

      LDA TEXT1,Y             ; CARACTERE POINTE PAR Y

      STA 24*40+1024,X        ; Ecrit à l’écran sur une cellule de la 23eme ligne

      INX                     ; Caractère et cellule suivante

      INY

      CPX #40                 ; index = 40 ?

      BNE .LOOP1             ; non on continue

      INC CURYS

      LDA SMOOTHVAL

      AND #$F8

      ORA #$07

      STA SMOOTHVAL           ; Remets SMOOTH X A 7

      BNE .NEXT2              ; A toujours <> de 0 pour eviter un JMP

.SMOOTHSCROLL:

      DEC SMOOTHVAL

.NEXT2:

; SPLIT BM->TEXT

       LDY #234

.WAIT234:

       CPY $D012           ; ligne 234 ?

       BNE .WAIT234 ; non on attends

; PASSE EN MODE TEXT

       LDA $D011

       AND #$DF            ; bit5=0 --> mode TEXT

       STA $D011           ; apply

       ; MOD SINGLE COLOR

       LDA $D016

       AND #$EF            ; bit 4 0 restore

       STA $D016

       ; Screen Memory en par defaut BASE+ $400

       LDA $D018

       AND #$F7            ; b3=0 => $0000

       STA $D018           ; APPLY

      ; SMOOTH SCROLL FOR TEXT

      NOP               ; SERIE DE NOP AVANT D'APPLIQUE LE SMOOTH SCROLL X

      NOP               ; SINON LE BASE DE L'IMAGE VA EGALEMENT SCROLLER

      NOP

      NOP

      NOP              

      LDA SMOOTHVAL     ; LECTURE DU SMOOTHX COURANT

      STA $D016         ; QU’ON APPLIQUE

; TOUCHE STOP/ESPACE POUR QUITTER

       ; ETC

CURYS:

      BYT 0

SMOOTHVAL:

      BYT 0

 

Et voilà nous venons de terminer notre premier crack-tro vous garder le corps du programme et vous n’avez qu’à changer l’image, le texte et la musique pour faire différemment. Vous pouvez également tenter d’ajouter un petit rasterbar, des Sprites ou tout ce qui vous passe par la tête. Il faudra juste veiller à ne pas en faire trop pour ne pas dépasser le nombre de cycle disponible mais nous avons beaucoup de marge.

Dans le listing complet ci-dessous, des variables CNT1, SMOOTHVAL2 et VALMOVIMGIDX apparaissent et deux série de texte en scroll s’affiche, lorsque le second texte défile, l’image bitmap bouge également en modifiant seulement le registre les 3 bits $D016 de la même façon que nous l’utilisons pour scroller le texte par pas de pixel. Cette fois-ci les valeurs du Smooth scroll de l’image sont stockées dans une table SMOOTHVAL2. Evidement seul des décalages de 7 pixels sont effectués mais vous pouvez déjà ici entrevoir comment effectuer un scrolling d’image de plus de 8 pixels.

 

; C64 TUTO SPLIT SCREEN

; DIVISION D'ECRAN SANS UTILISER D'INTERRUPTION

; LIGNE 0-181     BITMAP MC

; LIGNE 182-199 TEXTE

; PLAY SID

; SIMPLE SMOOTH SCROLL

; SMOOTH L'IMAGE TOUTES LES 2 FOIS

; TEXT DIFFERENT 1 FOIS SUR 2

ORG $0801

      BYT $0B,08,$0A,$00,$9E,$32,$30,$36,$34,$00           ; BASIC 10 SYS2064

ORG $0810

START:

; INIT COLOR BITMAP

      JSR COPYSCREENCOLOR

      JSR COPYVICCOLOR

; EFFACE LES LIGNE 23 ET 24 ET INITIALISE LEUR COULEUR

      LDX #$00                ; Index a 0

.LOOP1:

      LDA #$20                ; Espace pour effacer

      STA 23*40+1024,X        ; Ecrit à l’écran sur une cellule de la 23eme ligne

      STA 24*40+1024,X        ; Ecrit à l’écran sur une cellule de la 24eme ligne

      LDA #$01                ; Couleur blanche

      STA 23*40+$D800,X       ; Couleur de LIGNE 23

      STA 24*40+$D800,X       ; Couleur de LIGNE 24

      INX                     ; Caractère et cellule suivante

      CPX #40                 ; index = 40 ?

      BNE .LOOP1             ; non on continue

; INIT VIC

      LDX #$00                ; NOIRE

      STX $D020               ; POUR L’OVERSCAN

      LDA $4270               ; COULEUR DE FOND DE NOTRE IMAGE

      STA $D021               ; FOND

; AUTRE INITIALISATION ICI

      ;………………

      LDA #$00

      STA CURYS

      STA CNT1

      JSR $1000         ; INIT SID FILE        

      ; SMOOTH X SCROLL

      ; INIT CSEL $D016

      LDA $D016

      AND #$F0          ; Eteint les b3-b0

      ORA #$07          ; Scroll pas a 7

      STA $D016         ; Applique

      STA SMOOTHVAL

      STA SMOOTHVAL2

      SEI               ; DESACTIVE LES INTERRUPTIONS

MAIN:

; AVANT DE COMMENCER ON ATTEND QUE LA LIGNE HORIZONTAL ATTEIGNE LA PREMIERE LIGNE DU BAS DE L'OVERSCAN

      LDY #251

.WAIT251:

      CPY $D012

      BNE .WAIT251

      ; SMOOTH X SCROLL BITMAP

      LDA CNT1                ; LECTURE DU DRAPEAU

      BEQ .SMOOTHIMG          ; SI 0 ON NE BOUGE PAS L'IMAGE

      LDA SMOOTHVAL2          ; SINON ON COMMENCE PAR LIRE NOTRE VARIABLE SMOOTHVAL2

      AND #$F8                ; QUI ENREGISTRE LA DERNIERE VALEUR APPLIQUE AU REGISTRE $D016

      STA SMOOTHVAL2          ; DONT SEUL LES 3 DERNIERS BITS NOUS INTERRESSENT

      LDA VALMOVIMGIDX        ; VARIABLE INDEX EN COURS

      CLC

      ADC #$01                ; QU'ON INCRMENTE

      AND #$0F                ; TOUJOURS ENTRE 0 et 15

      STA VALMOVIMGIDX        ; ENREGISTRE l'INDEX COURANT

      TAX                     ; DANS X

      LDA VALMOVIMG,X         ; LECTRUE DU PAS SMOOTH X

      ORA SMOOTHVAL2          ; QU'ON APPLIQUE A SMOOTHVAL2

      STA SMOOTHVAL2         

.SMOOTHIMG:

      ; NEW SMOOTH

      LDA SMOOTHVAL2          ; RELECTURE DE SMOOTHVAL2

      STA $D016               ; QUE L'ON APPLIQUE

; ON PREPARE NOTRE BITMAP

      ; MODE BITMAP 1

      LDA $D011

      ORA #$20                ; BIT 5=1 -> MODE BITMAP

      STA $D011              

      ; MODE MULTICOLOR

      LDA $D016

      ORA #$10                ; BIT 4=1 -> MULTICOLOR

      STA $D016

      ; BITMAP ADRESSE

      LDA $D018              

      ORA #$08                ; B3=1 -> LE BITMAP EN $2000

      STA $D018              

; Au moins 13000 cyles disponible ici

      ;…………………

      ; PLAY SID

      JSR $1003               ; LECTURE DU SID

      ; SCROOL TEXT

.SCROLLT:

      LDA SMOOTHVAL           ; LECTURE DU SMOOTH X TEXT

      AND #$07                ; SEUL LES 3 DERNIERS BITS NOUS INTERESSE

      BEQ .BIGSCROLL          ; SI 0 ON PASSE A BIGSCROLL

      BNE .SMOOTHSCROLL       ; SINON ON EFFECTUE JUSTE LE SMOOTH X SCROLL

.BIGSCROLL:

      LDX #$00                ; INDEX X POSITION DE LA CELLULE DANS LA LIGNE

      LDY CURYS               ; INDEX Y POSITION COURANTE DANS LE TEXTE

.LOOP1:

      LDA TEXT1,Y             ; LECTURE D'UN CARACTERE DU TEXTE

      STA 24*40+1024,X        ; QUE L'ON ECRIS DANS LA CELLULE INDEXE PAR X DE LA LIGNE 24

      INX                     ; CELLULE SUIVANTE

      INY                     ; CARACTERE DU TEXTE SUIVANT

      CPX #40                 ; X = 40 ?

      BNE .LOOP1             ; NON ON CONTINUE

      INC CURYS               ; INCREMENTE L'INDEX DU TEXTE

      BNE .NEXT1              ; SI CURYS <> 0 ON PASSE A LA SUITE

      LDA CNT1                ; SINON NOUS MODIFIONS NOTRE DRAPEAU    

      EOR #$01                ; EN INVERSANT JUSTE LE BIT 0

      STA CNT1                ; CNT1 NE PEUT AVOIR QUE 2 VALEURS: 0 OU 1

      BNE .CHANGETXT2         ; SI CNT1 = 0

      LDA #TEXT1              ; LECTURE DE L'ADDRESSE BASSE DE TEXT1

      STA .LOOP1+1            ; SELF-MODYING

      LDA #>TEXT1             ; LECTURE DE L'ADDRESSE HAUTE DE TEXT1

      STA .LOOP1+2            ; SELF-MODYING

      BNE .NEXT1              ; SUITE

.CHANGETXT2:                 ; SINON C'EST LE TEXT2 QUE NOUS AFFICHONS

      LDA #TEXT2              ; LECTURE DE L'ADDRESSE BASSE DE TEXT1

      STA .LOOP1+1            ; SELF-MODYING

      LDA #>TEXT2             ; LECTURE DE L'ADDRESSE HAUTE DE TEXT1

      STA .LOOP1+2            ; SELF-MODYING

.NEXT1:

      LDA SMOOTHVAL           ; LECTURE DU SMOOTH SCROLL X DU TEXTE

      AND #$F8                ; SEUL LES 3 DERNIERS BITS NOUS INTERESSE

      ORA #$07                ; DECALAGE A DROITE MAXIMUM

      STA SMOOTHVAL           ; ENREGISTRE LE SMOOTH SCROLL X DU TEXTE

      BNE .NEXT2              ; A SERA TOUJOURS <> 0 CELA EVITE D'UTILISER UN JMP

.SMOOTHSCROLL:

      DEC SMOOTHVAL           ; SINON ON DECREMENTE SMOOTH SCROLL X DU TEXTE SANS APPLIQUER

.NEXT2:

; DIVISION D’ECRAN ICI BM->TEXT

      LDY #234

.WAIT234:

      CPY $D012               ; LIGNE 234 ?

      BNE .WAIT234            ; NON ON ATTEND

; PASSE EN MODE TEXT

      LDA $D011

      AND #$DF                ; BIT5=0 --> MODE TEXT

      STA $D011              

      ; MODE SINGLE COLOR

      LDA $D016

      AND #$EF                ; BIT4=0 -> SINGLE COLOR

      STA $D016

      ; SCREEN MEMORY PAR DEFAULT EN $0400

      LDA $D018

      AND #$F7                ; b3=0 => $0000

      STA $D018               ; APPLY

      LDA #$00                ; COULEUR DE FOND DE NOTRE TEXT

      STA $D021               ; FOND

      ; SMOOTH SCROLL FOR TEXT

      NOP               ; SERIE DE NOP AVANT D'APPLIQUE LE SMOOTH SCROLL X

      NOP               ; SINON LE BAS DE L'IMAGE VA EGALEMENT SCROLLER

      NOP

      NOP

      NOP              

      LDA SMOOTHVAL

      STA $D016

; TOUCHE STOP/ESPACE POUR QUITTER

      LDA $DC01

      CMP #$FF

      BNE .END

      JMP MAIN

.END:

      ; RESTORE VIC

      LDA $D011

      AND #$DF          ; bit5=0 --> mode TEXT

      STA $D011        

      ; MODE SINGLE COLOR

      LDA $D016

      AND #$E0          ; bit 4,3,2,1,0 to restore b4 0

      ORA #$08          ; bit 3 1 to 40 lignes

      STA $D016

      ; SCREEN MEMORY PAR DEFAULT EN $0400

      LDA $D018

      AND #$F7          ; b3=0 => $0000

      STA $D018        

      JSR $E544         ; CLEAR SCREEN

      LDX #$FE          ; Defaut overscan

      STX $D020  

      LDX #$F6          ; Defaut cadre

      STX $D021  

      ; COUPE LE SID

      LDA #$00

      STA $D418

      CLI         ; Reactive les interruptions

      BRK         ; Fin du programme

CURYS:

      BYT 0

SMOOTHVAL:

      BYT 0

SMOOTHVAL2:

      BYT 0

CNT1:

      BYT 0       ; DRAPEAU TEXT1/TEXT2

VALMOVIMG:

      BYT 7,6,5,4,3,2,1,0,1,2,3,4,5,6,7

VALMOVIMGIDX:

      BYT 0

COPYSCREENCOLOR:

      LDX #$00

.LOOP:

      LDA $3F40,X

      STA $0400,X

      LDA $4040,X

      STA $0500,X

      LDA $4140,X

      STA $0600,X

      LDA $4240,X

      STA $0700,X

      INX

      BNE .LOOP

      RTS

COPYVICCOLOR:

      LDX #$00

.LOOP:

      LDA $4328,X

      STA $D800,X

      LDA $4428,X

      STA $D900,X

      LDA $4528,X

      STA $DA00,X

      LDA $4628,X

      STA $DB00,X

      INX

      BNE .LOOP

      RTS

TEXT1:

      BYT "                                          "     ; 42 cellules

      BYT "BONJOUR TOUS LE MONDE !!!  NOUS SOMMES FIE"     ; 42 cellules     84

      BYT "RES DE VOUS PRESENTER NOTRE PREMIER CRACKT"     ; 42 cellules

      BYT "RO AVEC 1 DIVISION D'ECRAN BITMAP/TEXT ET "     ; 42 cellules     168

      BYT "AUCUNE INTERRUPTION UTILISEE !!! :) PLUS D"     ; 42 cellules     210

      BYT "'INFOS SUR COMMODOREHDCOVERS.XOOIT.FR CODI"     ; 42 cellules     252

      BYT "NG  "                                           ; 4 cellules      255

TEXT2:

      BYT "                                          "     ; 42 cellules

      BYT "ON PEUT EGALEMENT FAIRE BOUGER DE FACON TR"     ; 42 cellules     84

      BYT "ES SIMPLE L'IMAGE BITMAP EN JOUANT AVEC LE"     ; 42 cellules

      BYT " REGISTRE D016 DE LA MEME FACON QUE NOUS S"     ; 42 cellules     168

      BYT "CROLLONS LE TEXT PAR PAS DE 8 PIXELS. PLUS"    ; 42 cellules     210

BYT " D'INFOS SUR COMMODOREHDCOVERS.XOOIT.FR CO"     ; 42 cellules     252

      BYT "DING"                                           ; 4 cellules      255

; FICHIER SID INSERER DANS LE PROGRAMME EN ADRESSE $1000

ORG $1000-2

      INCBIN      "MYC64SID\\Loading.dat"

; FICHIER BITMAP INSERER DANS LE PROGRAMME EN ADRESSE $2000

ORG $2000-2

      INCBIN      "MYC64IMAGE\\vermeer.prg"

 

           

 

Ainsi ce termine cette première partie sur l’introduction à la programmation de petite intro.

J’espère que cela vous a plu J Sinon n’hésitez pas à m’écrire pour exposer vos critiques/objection.

Et surtout écrivez plein de petit programme. Je vous conseille, au début, l’écriture de divers petits programmes minimalistes que vous soignez ensuite peu à peu.

 

Dans la deuxième partie on verra comment utiliser les Sprites pour réaliser des choses étonnante sprite multicouleur, multiplexing. Ensuite nous verrons les interruptions. Puis on verra plus en détails le fonctionnement du VIC et comment il voit la mémoire, les Bad Lines et comment faire sauter les bords !!!