La Place des Développeurs Assembleur et gestion de la souris
Je continue donc mon exploration de la galaxie assembleur par la gestion de la souris.
En m'inspirant grandement de mon programme précédent, j'obtiens ce programme, qui pour le moment ne gère pas les détections de bord d'écran. Listing et ROM en pièce jointe !
souris.zip
En m'inspirant grandement de mon programme précédent, j'obtiens ce programme, qui pour le moment ne gère pas les détections de bord d'écran. Listing et ROM en pièce jointe !
;****** Deplacement avec souris en SCREEN 5 ******
;-------------------------------------------------
;*** Directives d'assemblage spécifique AsMSX ***
;-------------------------------------------------
.bios
.page 2
.rom
.start DEBUT
;---------------------------------------
;*** Adresses des tables du SCREEN 5 ***
;---------------------------------------
NAMTBL equ 0000h
SPRTBL equ 7800h
SPRATR equ 7600h
;--------------------------
;*** Début du programme ***
;--------------------------
DEBUT:
call DISSCR ; on coupe l'affichage
ld hl,0f3e9h ; on récupère l'adresse de la couleur d'écriture dans hl (zone de communication)
ld [hl],15 ; couleur d'écriture en blanc
inc hl ; on récupère l'adresse de la couleur de fond
ld [hl],0 ; couleur de fond transparente
inc hl ; on récupère l'adresse de la couleur de bordure
ld [hl],0 ; couleur de bordure transparente
;---------------------------
;*** Passage en SCREEN 5 ***
;---------------------------
ld a,5 ; on met le numéro de SCREEN choisi dans l'accumulateur
call CHGMOD ; appel de la routine BIOS CHGMOD
;-----------
;*** CLS ***
;-----------
ld hl,NAMTBL ; on met l'adresse de la table des noms dans hl
ld bc,27136 ; on met la longueur en octets de la table des noms (ici 27136) dans
; le registre double bc
xor a ; on annule la valeur de l'accumulateur
call FILVRM ; appel de la routine FILVRM (on remplit la VRAM à partir de l'adresse contenue par hl,
; sur une longueur d'octets contenue par bc, avec la valeur contenue par l'accumulateur
; ici 0, on remplit donc toute la table des noms par rien : on efface l'écran !
;----------------------------
;*** Définition du sprite ***
;----------------------------
ld hl,SPR_CUR ; on met dans hl l'adresse des données qui constituent notre sprite
ld de,SPRTBL ; on met dans de l'adresse de destination
ld bc,8 ; on met dans bc la longueur en octets des données à transférer
call LDIRVM ; on appelle la routine BIOS LDIRVM, qui va copier les données indiquées dans la VRAM
;---------------------------------------------------
;*** Définition des attributs de sprite initiaux ***
;---------------------------------------------------
ld hl,ATR_INITIAL ; on met hl à l'adresse de départ des attributs initiaux du sprite
ld de,SPRITES ; le registre de est mis à l'adresse de la zone variable
ld bc,4 ; le registre bc contient le nombre d'octets à transférer
ldir ; on copie bc (ici 4) octets depuis hl (ATR_INITIAL) vers de (SPRITES)
;---------------------------------
;*** Activation de l'affichage ***
;---------------------------------
call ENASCR ; on active l'affichage
;-------------------------
;*** Boucle principale ***
;-------------------------
LOOP: ; Label de la boucle principale
ld a,12 ; on charge 12 dans l'accumulateur : c'est la valeur qui permet d'initialiser la souris
; dans le port joystick n°1
ld ix,01adh ; on fait appelle à une routine (NEWPAD) de la Sub-ROM MSX2, on charge donc l'adresse
; de cette routine dans ix
call 015fh ; appel de la Sub-Rom MSX2 (en 015fh)
ld a,13 ; on charge 13 dans l'accumulateur : c'est la valeur qui va permettre de gérer le
; déplacement horizontal de la souris
ld ix,01adh ; voir au-dessus
call 015fh ; idem
ld b,a ; on charge dans b la valeur renvoyée par la routine (valeur du déplacement horizontal)
ld a,[SPRITES+1] ; on charge dans l'accu l'abscisse variable du curseur
add a,b ; on additionne l'abscisse et le déplacement horizontal
ld[SPRITES+1],a ; on remet dans l'adresse de la variable le résultat
ld a,14 ; toute cette partie est la même que la précédente
ld ix,01adh ; à ceci près que c'est la composante verticale qui
call 015fh ; est traitée
ld b,a ; cette fois !
ld a,[SPRITES]
add a,b
ld[SPRITES],a
call DUMP ; appel à la sous-routine DUMP (qui permet de transférer les valeurs en RAM vers la VRAM)
jp LOOP ; on boucle le programme
;------------------------------------------------
;*** Sous programme de transfert vers la VRAM ***
;------------------------------------------------
DUMP: ; label du sous-programme
halt ; synchronisation verticale
ld hl,SPRITES ; adresse de départ
ld de,SPRATR ; adresse d'arrivée
ld bc,4 ; longueur du bloc à transférer (en octets)
call LDIRVM ; appel à la routine BIOS LDIRVM
ret
;------------------
;*** Constantes ***
;------------------
ATR_INITIAL:
db 92,124,0,15
SPR_CUR:
db 010h,010h,010h,0eeh,010h,010h,010h,000h
;-----------------
;*** Variables ***
;-----------------
.page 3
SPRITES:
ds 4
;-------------------------------------------------
;*** Directives d'assemblage spécifique AsMSX ***
;-------------------------------------------------
.bios
.page 2
.rom
.start DEBUT
;---------------------------------------
;*** Adresses des tables du SCREEN 5 ***
;---------------------------------------
NAMTBL equ 0000h
SPRTBL equ 7800h
SPRATR equ 7600h
;--------------------------
;*** Début du programme ***
;--------------------------
DEBUT:
call DISSCR ; on coupe l'affichage
ld hl,0f3e9h ; on récupère l'adresse de la couleur d'écriture dans hl (zone de communication)
ld [hl],15 ; couleur d'écriture en blanc
inc hl ; on récupère l'adresse de la couleur de fond
ld [hl],0 ; couleur de fond transparente
inc hl ; on récupère l'adresse de la couleur de bordure
ld [hl],0 ; couleur de bordure transparente
;---------------------------
;*** Passage en SCREEN 5 ***
;---------------------------
ld a,5 ; on met le numéro de SCREEN choisi dans l'accumulateur
call CHGMOD ; appel de la routine BIOS CHGMOD
;-----------
;*** CLS ***
;-----------
ld hl,NAMTBL ; on met l'adresse de la table des noms dans hl
ld bc,27136 ; on met la longueur en octets de la table des noms (ici 27136) dans
; le registre double bc
xor a ; on annule la valeur de l'accumulateur
call FILVRM ; appel de la routine FILVRM (on remplit la VRAM à partir de l'adresse contenue par hl,
; sur une longueur d'octets contenue par bc, avec la valeur contenue par l'accumulateur
; ici 0, on remplit donc toute la table des noms par rien : on efface l'écran !
;----------------------------
;*** Définition du sprite ***
;----------------------------
ld hl,SPR_CUR ; on met dans hl l'adresse des données qui constituent notre sprite
ld de,SPRTBL ; on met dans de l'adresse de destination
ld bc,8 ; on met dans bc la longueur en octets des données à transférer
call LDIRVM ; on appelle la routine BIOS LDIRVM, qui va copier les données indiquées dans la VRAM
;---------------------------------------------------
;*** Définition des attributs de sprite initiaux ***
;---------------------------------------------------
ld hl,ATR_INITIAL ; on met hl à l'adresse de départ des attributs initiaux du sprite
ld de,SPRITES ; le registre de est mis à l'adresse de la zone variable
ld bc,4 ; le registre bc contient le nombre d'octets à transférer
ldir ; on copie bc (ici 4) octets depuis hl (ATR_INITIAL) vers de (SPRITES)
;---------------------------------
;*** Activation de l'affichage ***
;---------------------------------
call ENASCR ; on active l'affichage
;-------------------------
;*** Boucle principale ***
;-------------------------
LOOP: ; Label de la boucle principale
ld a,12 ; on charge 12 dans l'accumulateur : c'est la valeur qui permet d'initialiser la souris
; dans le port joystick n°1
ld ix,01adh ; on fait appelle à une routine (NEWPAD) de la Sub-ROM MSX2, on charge donc l'adresse
; de cette routine dans ix
call 015fh ; appel de la Sub-Rom MSX2 (en 015fh)
ld a,13 ; on charge 13 dans l'accumulateur : c'est la valeur qui va permettre de gérer le
; déplacement horizontal de la souris
ld ix,01adh ; voir au-dessus
call 015fh ; idem
ld b,a ; on charge dans b la valeur renvoyée par la routine (valeur du déplacement horizontal)
ld a,[SPRITES+1] ; on charge dans l'accu l'abscisse variable du curseur
add a,b ; on additionne l'abscisse et le déplacement horizontal
ld[SPRITES+1],a ; on remet dans l'adresse de la variable le résultat
ld a,14 ; toute cette partie est la même que la précédente
ld ix,01adh ; à ceci près que c'est la composante verticale qui
call 015fh ; est traitée
ld b,a ; cette fois !
ld a,[SPRITES]
add a,b
ld[SPRITES],a
call DUMP ; appel à la sous-routine DUMP (qui permet de transférer les valeurs en RAM vers la VRAM)
jp LOOP ; on boucle le programme
;------------------------------------------------
;*** Sous programme de transfert vers la VRAM ***
;------------------------------------------------
DUMP: ; label du sous-programme
halt ; synchronisation verticale
ld hl,SPRITES ; adresse de départ
ld de,SPRATR ; adresse d'arrivée
ld bc,4 ; longueur du bloc à transférer (en octets)
call LDIRVM ; appel à la routine BIOS LDIRVM
ret
;------------------
;*** Constantes ***
;------------------
ATR_INITIAL:
db 92,124,0,15
SPR_CUR:
db 010h,010h,010h,0eeh,010h,010h,010h,000h
;-----------------
;*** Variables ***
;-----------------
.page 3
SPRITES:
ds 4
souris.zip
MSX un jour, MSX toujours !
une solution serait de na pas déplacer le sprite directement avec les coordonnées de la souris
mais de passer par une variable intermédiaire qui elle serait comparée aux valeurs de limitations d'écran comme dans l'exemple avec le clavier
enfin ce n'est qu'une suggestion a toi de voir
mais de passer par une variable intermédiaire qui elle serait comparée aux valeurs de limitations d'écran comme dans l'exemple avec le clavier
enfin ce n'est qu'une suggestion a toi de voir
Ca marche... presque ! En fait, on dirait que lorsque le mouvement de la souris est trop rapide, le test des bords n'est pas fait... Je me demande s'il ne faut pas que je fasse un test de signe sur le déplacement
MSX un jour, MSX toujours !
Walter
Membre non connecté
Conseiller Municipal
Walter :
D'après ce que je lis, tu boucles le programme sans vérifier les coordonnées du pointeur par rapport à sa position précédente granced. C'est normal ?
Non non, tu n'as pas rêvé, je ne fais pas de test de ce genre, du moins pas dans le listing ci-présent. Je me creuse la tête pour trouver une solution pour la gestion des bords mais c'est un peu le casse-tête !
En fait ce qui est renvoyé par la routine NEWPAD, c'est le déplacement relatif de la souris (donc un entier signé !). Je me demande s'il ne faut pas que je regarde à ça.
Jipe :
il faut simuler un > ou < car si tu ne passe pas par la coordonnée pile exacte avec la souris le calcul est faussé
J'ai fait des essais dans ce but, mais pour l'instant sans résultat probant (utilisation de C lors du CP : si l'accu A est a une certaine valeur, un CP op réalise A-op. Si A-op>=0, C=0, si A-op<0, C=1). Je fais des essais aussi avec P et M pour le signe
MSX un jour, MSX toujours !
La tache est ardue
Pour vérifier si un entier signé est négatif il faut vérifier s'il est supérieur à 128 (10000000 en binaire) en vérifiant le bit 7 (le premier en partant de la gauche, les bits étant numérotés de0 à 7 de droite à gauche ). Un bit 7,b renvoie 1 dans Z s'il est supérieur à 128 (1000000, 10000001, 10000010... 11111111).
Pour vérifier si a dépasse une certaine valeur (dans mon exemple 240(11110000)) je fais and 240[ , le a and 240 ne renverra 240 que si a est supérieur ou égal à 240.
voir AND
exemples:
1111 1110 AND
1111 0000
1111 0000
0111 1111 AND
1111 0000
0111 0000
Après il suffit de comparer a à 240 pour savoir si la précédente valeur en abscisse de la souris est supérieure ou égale à 240.
Je n'est testé que sur émulateur et un mouvement brusque de la souris crée un bug.
Je me creuse la tête pour les "inférieur à" mais ça me parait plus compliqué...
souris.zip
Pour vérifier si un entier signé est négatif il faut vérifier s'il est supérieur à 128 (10000000 en binaire) en vérifiant le bit 7 (le premier en partant de la gauche, les bits étant numérotés de0 à 7 de droite à gauche ). Un bit 7,b renvoie 1 dans Z s'il est supérieur à 128 (1000000, 10000001, 10000010... 11111111).
Pour vérifier si a dépasse une certaine valeur (dans mon exemple 240(11110000)) je fais and 240[ , le a and 240 ne renverra 240 que si a est supérieur ou égal à 240.
voir AND
exemples:
1111 1110 AND
1111 0000
1111 0000
0111 1111 AND
1111 0000
0111 0000
Après il suffit de comparer a à 240 pour savoir si la précédente valeur en abscisse de la souris est supérieure ou égale à 240.
Je n'est testé que sur émulateur et un mouvement brusque de la souris crée un bug.
Je me creuse la tête pour les "inférieur à" mais ça me parait plus compliqué...
;-------------------------
;*** Boucle principale ***
LOOP: ; Label de la boucle principale
ld a,12 ; on charge 12 dans l'accumulateur : c'est la valeur qui permet d'initialiser la souris
; dans le port joystick n°1
ld ix,01adh ; on fait appelle à une routine (NEWPAD) de la Sub-ROM MSX2, on charge donc l'adresse
; de cette routine dans ix
call 015fh ; appel de la Sub-Rom MSX2 (en 015fh)
ld a,13 ; on charge 13 dans l'accumulateur : c'est la valeur qui va permettre de gérer le
; déplacement horizontal de la souris
ld ix,01adh ; voir au-dessus
call 015fh ; idem
ld b,a ; on charge dans b la valeur renvoyée par la routine (valeur du déplacement horizontal)
ld a,[SPRITES+1]; on charge dans l'accu l'abscisse variable du curseur
push af ;sauvegarde de a
and 240 ;on met a à 240 si supérieur
cp a,240 ;on compare si a=240
jr nz,suiteh ;sinon mvt normal
bit 7,b ;on vérifie si le mouvement de la souris est négatif
;bit7 de b à 1 implique que b>=128 donc z=1 indique que b est négatif
jr z,finh ;abandon si positif
suiteh:
pop af ;récupération de a
add a,b ; on additionne l'abscisse et le déplacement horizontal
ld[SPRITES+1],a ; on remet dans l'adresse de la variable le résultat
finh:
ld a,14 ; toute cette partie est la même que la précédente
ld ix,01adh ; à ceci près que c'est la composante verticale qui
call 015fh ; est traitée
ld b,a ; cette fois !
ld a,[SPRITES]
add a,b
ld[SPRITES],a
call DUMP ; appel à la sous-routine DUMP (qui permet de transférer les valeurs en RAM vers la VRAM)
jp LOOP ; on boucle le programme
;*** Boucle principale ***
LOOP: ; Label de la boucle principale
ld a,12 ; on charge 12 dans l'accumulateur : c'est la valeur qui permet d'initialiser la souris
; dans le port joystick n°1
ld ix,01adh ; on fait appelle à une routine (NEWPAD) de la Sub-ROM MSX2, on charge donc l'adresse
; de cette routine dans ix
call 015fh ; appel de la Sub-Rom MSX2 (en 015fh)
ld a,13 ; on charge 13 dans l'accumulateur : c'est la valeur qui va permettre de gérer le
; déplacement horizontal de la souris
ld ix,01adh ; voir au-dessus
call 015fh ; idem
ld b,a ; on charge dans b la valeur renvoyée par la routine (valeur du déplacement horizontal)
ld a,[SPRITES+1]; on charge dans l'accu l'abscisse variable du curseur
push af ;sauvegarde de a
and 240 ;on met a à 240 si supérieur
cp a,240 ;on compare si a=240
jr nz,suiteh ;sinon mvt normal
bit 7,b ;on vérifie si le mouvement de la souris est négatif
;bit7 de b à 1 implique que b>=128 donc z=1 indique que b est négatif
jr z,finh ;abandon si positif
suiteh:
pop af ;récupération de a
add a,b ; on additionne l'abscisse et le déplacement horizontal
ld[SPRITES+1],a ; on remet dans l'adresse de la variable le résultat
finh:
ld a,14 ; toute cette partie est la même que la précédente
ld ix,01adh ; à ceci près que c'est la composante verticale qui
call 015fh ; est traitée
ld b,a ; cette fois !
ld a,[SPRITES]
add a,b
ld[SPRITES],a
call DUMP ; appel à la sous-routine DUMP (qui permet de transférer les valeurs en RAM vers la VRAM)
jp LOOP ; on boucle le programme
souris.zip
Le MSXien le plus à l'ouest ... ou presque
Oui j'ai eu le même souci...
Lorsque la valeur du déplacement est trop importante, le test de détection des bords échoue...
L'adaptation du programme en Basic ne pose quant à elle pas ce genre de problème... Trop rapide l'assembleur ?
En y réfléchissant, je me dis qu'il y a forcément une autre méthode : si le déplacement est trop important, alors il faut le limiter à la différence entre le bord à traiter et la position du curseur. Je détaille un peu mon raisonnement, (pour le bord gauche pour un déplacement horizontal) vers la gauche avant de le tenter en prog :
Imaginons que mon curseur soit en position (10,Y). Je mets un grand coup de souris à gauche, mon déplacement est de -127, ça va foirer. Par contre si je vois que le déplacement est inférieur à 0-coordonnée X (ici -10 donc), je le limite à -10. Ca va me forcer à effectuer aussi un test en fonction de la coordonnée X de mon curseur, cette méthode n'étant valable à mon avis que lorsque le curseur est entre 0 et 127 en abscisse. Pfff, que c'est compliqué !!!
Lorsque la valeur du déplacement est trop importante, le test de détection des bords échoue...
L'adaptation du programme en Basic ne pose quant à elle pas ce genre de problème... Trop rapide l'assembleur ?
En y réfléchissant, je me dis qu'il y a forcément une autre méthode : si le déplacement est trop important, alors il faut le limiter à la différence entre le bord à traiter et la position du curseur. Je détaille un peu mon raisonnement, (pour le bord gauche pour un déplacement horizontal) vers la gauche avant de le tenter en prog :
Imaginons que mon curseur soit en position (10,Y). Je mets un grand coup de souris à gauche, mon déplacement est de -127, ça va foirer. Par contre si je vois que le déplacement est inférieur à 0-coordonnée X (ici -10 donc), je le limite à -10. Ca va me forcer à effectuer aussi un test en fonction de la coordonnée X de mon curseur, cette méthode n'étant valable à mon avis que lorsque le curseur est entre 0 et 127 en abscisse. Pfff, que c'est compliqué !!!
MSX un jour, MSX toujours !
Walter
Membre non connecté
Conseiller Municipal
C'est pour cela que je parlais de vérifier les coordonnées.
Est-il possible de définir un "pas" de déplacement pour ta souris granced, et ainsi controler sa vitesse et peut-être bloquer les abscisses et ordonnées ?
Si cela peut t'inspirer, en MSX-Basic, je procède ainsi :
Selon le mode écran utilisé, Il suffit de changer les valeur MAX SX en ligne 150 et SY en ligne 170.
Es-tu obligé d'initialiser le port à chaque boucle ?
Est-il possible de définir un "pas" de déplacement pour ta souris granced, et ainsi controler sa vitesse et peut-être bloquer les abscisses et ordonnées ?
Si cela peut t'inspirer, en MSX-Basic, je procède ainsi :
Selon le mode écran utilisé, Il suffit de changer les valeur MAX SX en ligne 150 et SY en ligne 170.
granced :
ld a,12 ; on charge 12 dans l'accumulateur : c'est la valeur qui permet d'initialiser la souris
; dans le port joystick n°1
; dans le port joystick n°1
Es-tu obligé d'initialiser le port à chaque boucle ?
En Basic c'est plus facile je pense parce que les tests des valeurs prennent bien en compte que ce sont des entiers signés (le déplacement maximal est de + ou -127, en assembleur ce n'est pas aussi facile j'ai l'impression... Il doit y avoir un truc à faire avec un des bits du registre F (le bit P/V).
Le déplacement est codé sur un octet allant de 0h à FFh, sachant que de 0h à 7Fh ce sont les déplacements positifs (vers la droite ou vers le bas), et de 80h à FFh les déplacements négatifs (vers la gauche et vers le haut). Si on prend une des coordonnées et qu'on l'ajoute à ce déplacement, les tests sont faussés (imaginons que je sois à l'abscisse 200 et que je fasse un déplacement de 127 vers la droite, et que ma borne maximale est de 240 : en hexa j'ai C8h + 7Fh, j'obtiens 47h (avec une retenue), ma borne maximale est F0h. Mon test pour le bord droit est de rejeter toute coordonnée supérieure à F0h, or 47h est bien inférieur à F0h : test foiré...
Le déplacement est codé sur un octet allant de 0h à FFh, sachant que de 0h à 7Fh ce sont les déplacements positifs (vers la droite ou vers le bas), et de 80h à FFh les déplacements négatifs (vers la gauche et vers le haut). Si on prend une des coordonnées et qu'on l'ajoute à ce déplacement, les tests sont faussés (imaginons que je sois à l'abscisse 200 et que je fasse un déplacement de 127 vers la droite, et que ma borne maximale est de 240 : en hexa j'ai C8h + 7Fh, j'obtiens 47h (avec une retenue), ma borne maximale est F0h. Mon test pour le bord droit est de rejeter toute coordonnée supérieure à F0h, or 47h est bien inférieur à F0h : test foiré...
MSX un jour, MSX toujours !
En basic c'est plus facile car on utilise une variable (entière) limitée de -32768 à +32767, contrairement à notre pauvre accumulateur qui lui "s'étend" de -127 à 128 (0-255) en fait on est comme sur un cylindre (dans les deux sens x et y ) autant l'empêcher de rouler, c'est quasi injouable.
Il faudrait jouer sur un double registre avant l'affichage pour que ce soit jouable. Petit rappel un call DCOMPR (0020 h) permet de comparer HL et DE et renvoie 1 dans Z siHL=DE et 1 dans carry si HL<DE. C'est une piste à explorer je pense!
SOS: Quelqu'un a des nouvelles de Metalion
Il faudrait jouer sur un double registre avant l'affichage pour que ce soit jouable. Petit rappel un call DCOMPR (0020 h) permet de comparer HL et DE et renvoie 1 dans Z siHL=DE et 1 dans carry si HL<DE. C'est une piste à explorer je pense!
SOS: Quelqu'un a des nouvelles de Metalion
Le MSXien le plus à l'ouest ... ou presque
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie