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
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 !!!