Revenir au plan du site

Un programme "Télécran", évolution pour gérer les diagonales

Comme vous l'avez sûrement remarqué à l'exécution du programme, l'appui d'une touche fait revenir de suite à l'affichage du point, de sorte qu'il n'est pas possible de faire une diagonale, bien qu'on appuie simultanément sur deux touches à la fois.

Pour rendre le tracé de diagonale possible, il faut différer l'affichage du point et continuer à traiter les autres touches, même si on a appuyé sur une d'entre elles. La logique change, et pour nous aider, nous allons passer par une variable temporaire qui nous indiquera en fin de boucle si nous devons afficher à nouveau ou pas. De plus, au lieu de sauter dans nos routines, nous allons faire un CALL conditionnel et un RET dans les sous-routines.

Voici la modification au niveau des touches (utilisation de XL comme flag, appel aux routines avec un CALL au lieu d'un JP sans retour)
ld xl,0 ; on met zéro dans XL par défaut, si une touche est appuyée on y mettra 1
ld a,(OCTET_CURSEUR_HAUT) : and BIT_CURSEUR_HAUT : call z,gererHaut
ld a,(OCTET_CURSEUR_BAS) : and BIT_CURSEUR_BAS : call z,gererBas
ld a,(OCTET_CURSEUR_DROITE) : and BIT_CURSEUR_DROITE : call z,gererDroite
ld a,(OCTET_CURSEUR_GAUCHE) : and BIT_CURSEUR_GAUCHE : call z,gererGauche
ld a,xl : or a
jp nz,AfficherPoint ; on affiche le point quand XL différent de zéro

Et dans chaque routine (je n'en mets qu'une seule ici), un RET Z si on ne fait rien, un INC XL : RET dans le cas de la validation du changement. On a remplacé tous les JP de sortie par RET, car on veut revenir dans la gestion des touches pour traiter toutes les touches.
gererHaut
ld hl,(positiony)
ld a,h : or l : ret z ; 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
inc xl ; flag affichage!
ret ; on remonte afficher le point

Enfin, le source complet avec gestion des diagonales.
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 allez on speed un peu à 17 images 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 xl,0 ; on met zéro dans XL par défaut, si une touche est appuyée on y mettra 1
ld a,(OCTET_CURSEUR_HAUT) : and BIT_CURSEUR_HAUT : call z,gererHaut
ld a,(OCTET_CURSEUR_BAS) : and BIT_CURSEUR_BAS : call z,gererBas
ld a,(OCTET_CURSEUR_DROITE) : and BIT_CURSEUR_DROITE : call z,gererDroite
ld a,(OCTET_CURSEUR_GAUCHE) : and BIT_CURSEUR_GAUCHE : call z,gererGauche
ld a,xl : or a
jp nz,AfficherPoint ; on affiche le point quand XL différent de zéro
;
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 : ret z ; 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
inc xl ; flag affichage!
ret ; on remonte afficher le point
;
gererGauche
ld hl,(positionx)
ld a,h : or l : ret z
dec hl
ld (positionx),hl
inc xl ; flag affichage!
ret ; on remonte afficher le point
;
gererBas
ld hl,(positiony)
ld a,l : cp 199 : ret z ; 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
inc xl ; flag affichage!
ret ; on remonte afficher le point
gererDroite
ld hl,(positionx)
ld a,l : cp lo(319) : jr nz,.okDroite
ld a,h : cp hi(319) : ret z
.okDroite
inc hl
ld (positionx),hl
inc xl ; flag affichage!
ret ; on remonte afficher le point
;======================================
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