CODINGApprendre pas à pas la programmation en assembleur Z80 par Roudoudou ★ Fusion de quelques briques élémentaires pour créer un petit jeu ★

Le jeu du Télécran partie 2 (corrections des défauts)
Un programme "Télécran", source complet et correction de l'affichage ;)

Voici le source complet de nos assemblages (spoiler : il manque encore quelque chose mais c'est fonctionnel)

           BUILDSNA : BANKSET 0
ORG #100 : RUN #100

;======================================
EffaceEcran
;======================================
ld hl,#C000
xor a ; A=0
.loop
ld (hl),a  ; écrire #00 à l'adresse pointée par HL
inc l ; incrémenter seulement L positionne le flag Z une fois revenu à zéro
jr nz,.loop ; on boucle donc tant que L est différent de zéro
inc h ; même chose pour H, sauf que nous savons ici que L vaut zéro
jr nz,.loop ; tant que H ne vaut pas zéro on reboucle
; ici nous avons HL=#0000 nous sommes revenus au début de la mémoire, l'écran est effacer, on s'arrête

; initialiser les coordonnées de notre point
ld hl,160 : ld (positionx),hl
ld hl,100 : ld (positiony),hl

;======================================
AfficherPoint
;======================================
ld bc,(positionx)
ld hl,(positiony)
call CalculeAdressePixel
ld (hl),c ; écrire le pixel à l'écran

;======================================
LireLeClavier
;======================================
call lectureMatriceClavier

OCTET_CURSEUR_HAUT equ matriceClavier : BIT_CURSEUR_HAUT equ 1
OCTET_CURSEUR_DROITE equ matriceClavier : BIT_CURSEUR_DROITE equ 2
OCTET_CURSEUR_BAS equ matriceClavier : BIT_CURSEUR_BAS equ 4
OCTET_CURSEUR_GAUCHE equ matriceClavier+1 : BIT_CURSEUR_GAUCHE equ 1
OCTET_TOUCHE_ESPACE equ matriceClavier+5 : BIT_TOUCHE_ESPACE equ 128

; si on appuie sur Espace, on revient à l'effacement de l'écran
ld a,(OCTET_TOUCHE_ESPACE) : and BIT_TOUCHE_ESPACE : jp z,EffaceEcran

; touches du curseur
ld a,(OCTET_CURSEUR_HAUT) : and BIT_CURSEUR_HAUT : jp z,gererHaut
ld a,(OCTET_CURSEUR_BAS) : and BIT_CURSEUR_BAS : jp z,gererBas
ld a,(OCTET_CURSEUR_DROITE) : and BIT_CURSEUR_DROITE : jp z,gererDroite
ld a,(OCTET_CURSEUR_GAUCHE) : and BIT_CURSEUR_GAUCHE : jp z,gererGauche
;
jp LireLeClavier ; ni espace, ni curseur, on continue de lire le clavier
;======================================
; sous-routines de gestion des touches
;======================================
gererHaut
ld hl,(positiony)
ld a,h : or l : jp z,LireLeClavier ; si le Y vaut zéro on est déjà en haut de l'écran
dec hl ; on n'est pas en haut alors on décrémente
ld (positiony),hl ; et on valide la nouvelle coordonnée
jp AfficherPoint ; on remonte afficher le point
;
gererGauche
ld hl,(positionx)
ld a,h : or l : jp z,LireLeClavier
dec hl
ld (positionx),hl
jp AfficherPoint
;
gererBas
ld hl,(positiony)
ld a,l : cp 199 : jp z,LireLeClavier ; si le Y vaut 199 on est déjà en bas de l'écran
inc hl ; on peut incrémenter
ld (positiony),hl ; et on valide la nouvelle coordonnée
jp AfficherPoint ; on remonte afficher le point
gererDroite
ld hl,(positionx)
ld a,l : cp lo(319) : jr nz,.okDroite
ld a,h : cp hi(319) : jp z,LireLeClavier
.okDroite
inc hl
ld (positionx),hl
jp AfficherPoint
;======================================
CalculeAdressePixel
;======================================
; BC=coordonnée X (0-319)
; HL=coordonnée Y (0-199)
ld de,tableau
add hl,hl ; adresses 16 bits, il faut indexer de 2 en 2
add hl,de
ld a,(hl) : inc hl
ld h,(hl) : ld l,a
; HL=adresse de la ligne
ld a,c ; on sauvegarde le X avant de diviser par 4
srl bc : srl bc ; diviser le X par 4 pour avoir l'octet en mode 1
add hl,bc
ld c,%10000000 ; encre 1 pour le pixel mode 1 le plus à gauche dans l'octet
and 3 ; avec le modulo 4 on va savoir quel est le pixel en partant de la gauche
jr z,.noShift
.Shift
srl c
dec a
jr nz,.Shift
.noShift
ret ; HL=adresse écran aux coordonnées X/Y données et C est le pixel d'encre 1
;-------------------
adresse_ecran=#C000
largeur_ecran=80
tableau
repeat 25
repeat 8
defw adresse_ecran
adresse_ecran+=#800
rend
adresse_ecran+=largeur_ecran
adresse_ecran-=#4000
rend
;======================================
lectureMatriceClavier
;======================================
ld hl,matriceClavier
ld bc,#f782
out (c),c
ld bc,#f40e
ld e,b
out (c),c
ld bc,#f6c0
ld d,b
out (c),c
out (c),0
ld bc,#f792
out (c),c
ld a,#40
ld c,d
.loop ld b,d
out (c),a ; sélectionner la ligne
ld b,e
ini  ; lire et stocker dans notre tableau
inc a
inc c
jr nz,.loop
ret

matriceClavier defs 10,#FF
;=================================================
; en fin du programme, nos coordonnées sur 16 bits
;=================================================
positionx defw 0
positiony defw 0


Vous lancez le programme et là, deux problèmes majeurs :1/ Ça va trop vite, vous programmez trop bien.
2/ Comme il y a 4 points par octet, afficher un point en efface jusqu'à 3 autres.

Ralentir le programme, on sait faire, on va ajouter deux ou trois attentes de VBL.

Pour le masquage écran, nous allons lire la valeur à l'adresse destination pointée par HL, la fusionner à notre point avec un OR et enfin l'écrire.

           ; au lieu de
ld (hl),c
; il faudra faire
ld a,(hl) ; copier l'octet de l'écran dans A
or c ; fusionner avec le nouveau pixel
ld (hl),a ; écrire le nouvel octet

Et voici le source complet ET corrigé ^_^

           BUILDSNA : BANKSET 0
ORG #100 : RUN #100

;======================================
EffaceEcran
;======================================
ld hl,#C000
xor a ; A=0
.loop
ld (hl),a  ; écrire #00 à l'adresse pointée par HL
inc l ; incrémenter seulement L positionne le flag Z une fois revenu à zéro
jr nz,.loop ; on boucle donc tant que L est différent de zéro
inc h ; même chose pour H, sauf que nous savons ici que L vaut zéro
jr nz,.loop ; tant que H ne vaut pas zéro on reboucle
; ici nous avons HL=#0000 nous sommes revenus au début de la mémoire, l'écran est effacer, on s'arrête

; initialiser les coordonnées de notre point
ld hl,160 : ld (positionx),hl
ld hl,100 : ld (positiony),hl

;======================================
AfficherPoint
;======================================
ld bc,(positionx)
ld hl,(positiony)
call CalculeAdressePixel
ld a,(hl) : or c : ld (hl),a ; fusionner le pixel à l'écran

call waitVBLstart ; 50Hz
call waitVBLstart ; 25Hz
call waitVBLstart ; 17Hz
call waitVBLstart ; 12Hz nous afficherons 12 pixels par seconde

;======================================
LireLeClavier
;======================================
call lectureMatriceClavier

OCTET_CURSEUR_HAUT equ matriceClavier : BIT_CURSEUR_HAUT equ 1
OCTET_CURSEUR_DROITE equ matriceClavier : BIT_CURSEUR_DROITE equ 2
OCTET_CURSEUR_BAS equ matriceClavier : BIT_CURSEUR_BAS equ 4
OCTET_CURSEUR_GAUCHE equ matriceClavier+1 : BIT_CURSEUR_GAUCHE equ 1
OCTET_TOUCHE_ESPACE equ matriceClavier+5 : BIT_TOUCHE_ESPACE equ 128

; si on appuie sur Espace, on revient à l'effacement de l'écran
ld a,(OCTET_TOUCHE_ESPACE) : and BIT_TOUCHE_ESPACE : jp z,EffaceEcran

; touches du curseur
ld a,(OCTET_CURSEUR_HAUT) : and BIT_CURSEUR_HAUT : jp z,gererHaut
ld a,(OCTET_CURSEUR_BAS) : and BIT_CURSEUR_BAS : jp z,gererBas
ld a,(OCTET_CURSEUR_DROITE) : and BIT_CURSEUR_DROITE : jp z,gererDroite
ld a,(OCTET_CURSEUR_GAUCHE) : and BIT_CURSEUR_GAUCHE : jp z,gererGauche
;
jp LireLeClavier ; ni espace, ni curseur, on continue de lire le clavier
;======================================
; sous-routines de gestion des touches
;======================================
gererHaut
ld hl,(positiony)
ld a,h : or l : jp z,LireLeClavier ; si le Y vaut zéro on est déjà en haut de l'écran
dec hl ; on n'est pas en haut alors on décrémente
ld (positiony),hl ; et on valide la nouvelle coordonnée
jp AfficherPoint ; on remonte afficher le point
;
gererGauche
ld hl,(positionx)
ld a,h : or l : jp z,LireLeClavier
dec hl
ld (positionx),hl
jp AfficherPoint
;
gererBas
ld hl,(positiony)
ld a,l : cp 199 : jp z,LireLeClavier ; si le Y vaut 199 on est déjà en bas de l'écran
inc hl ; on peut incrémenter
ld (positiony),hl ; et on valide la nouvelle coordonnée
jp AfficherPoint ; on remonte afficher le point
gererDroite
ld hl,(positionx)
ld a,l : cp lo(319) : jr nz,.okDroite
ld a,h : cp hi(319) : jp z,LireLeClavier
.okDroite
inc hl
ld (positionx),hl
jp AfficherPoint
;======================================
CalculeAdressePixel
;======================================
; BC=coordonnée X (0-319)
; HL=coordonnée Y (0-199)
ld de,tableau
add hl,hl ; adresses 16 bits, il faut indexer de 2 en 2
add hl,de
ld a,(hl) : inc hl
ld h,(hl) : ld l,a
; HL=adresse de la ligne
ld a,c ; on sauvegarde le X avant de diviser par 4
srl bc : srl bc ; diviser le X par 4 pour avoir l'octet en mode 1
add hl,bc
ld c,%10000000 ; encre 1 pour le pixel mode 1 le plus à gauche dans l'octet
and 3 ; avec le modulo 4 on va savoir quel est le pixel en partant de la gauche
jr z,.noShift
.Shift
srl c
dec a
jr nz,.Shift
.noShift
ret ; HL=adresse écran aux coordonnées X/Y données et C est le pixel d'encre 1
;-------------------
adresse_ecran=#C000
largeur_ecran=80
tableau
repeat 25
repeat 8
defw adresse_ecran
adresse_ecran+=#800
rend
adresse_ecran+=largeur_ecran
adresse_ecran-=#4000
rend
;==============
waitVBLstart
;==============
ld b,#F5
.loop in a,(c) : rra : jr c,.loop ; attendre l'absence de VBL
;==============
waitVBL
;==============
ld b,#F5
.loop in a,(c) : rra : jr nc,.loop ; attendre la VBL
ret
;======================================
lectureMatriceClavier
;======================================
ld hl,matriceClavier
ld bc,#f782
out (c),c
ld bc,#f40e
ld e,b
out (c),c
ld bc,#f6c0
ld d,b
out (c),c
out (c),0
ld bc,#f792
out (c),c
ld a,#40
ld c,d
.loop ld b,d
out (c),a ; sélectionner la ligne
ld b,e
ini  ; lire et stocker dans notre tableau
inc a
inc c
jr nz,.loop
ret

matriceClavier defs 10,#FF
;=================================================
; en fin du programme, nos coordonnées sur 16 bits
;=================================================
positionx defw 0
positiony defw 0

Roudoudou

★ ANNÉE: 2025
★ AUTEUR: Roudoudou

Je participe au site:

» Vous avez remarqué une erreur dans ce texte ?
» Aidez-nous à améliorer cette page : en nous contactant via le forum ou par email.

CPCrulez[Content Management System] v8.732-desktop/c
Page créée en 603 millisecondes et consultée 23 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.