Obligement - L'Amiga au maximum

Vendredi 19 avril 2019 - 00:22  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Articles divers

 · Articles in english
 · Articles en d'autres langues


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Logiciels
 · Jeux
 · Scène démo
 · Divers


Jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Contact

David Brunet

Courriel

 


Programmation : Assembleur - Routine de lecture de la position des manettes
(Article écrit par Stéphane Schreiber et extrait d'Amiga News Tech - septembre 1991)


Quand on s'attaque à l'écriture d'un jeu, on a toujours besoin d'une routine de lecture de la position des manettes, par exemple pour décider du mouvement à donner à un sprite et/ou à un défilement. Bien que cela ne soit pas réellement compliqué sur l'Amiga, les routines habituelles ne sont pas forcément les meilleures.

Bien que le matériel de l'Amiga l'autorise à utiliser des manettes analogiques - ou "proportionnels" - comme l'IBM PC ou l'Apple II, le type le plus courant est celui mis au point par Atari à l'époque de sa console de jeu, la VCS 2600, qui offre simplement quatre commutateurs, un par dilection possible (haut, bas, gauche, droite) et qui a été repris par de multiples constructeurs, dont Commodore (on parle d'ailleurs de "standard Atari" pour ce type de manettes, autant leur laisser au moins ça...). Sur des systèmes plus anciens, comme le C64 ou l'Amstrad CPC, il suffisait de lire un octet en mémoire ou sur un port pour savoir immédiatement dans quelle(s) direction(s) la manette était poussée.

Sur l'Amiga, pour des raisons incompréhensibles, c'est un peu plus compliqué ; les bits "haut" et "gauche" occupent deux bits d'un octet, et les "bas" et "droite", deux bits d'un autre octet d'état du ou des boutons de feu étant quant à lui encore ailleurs. Bien qu'il soit toujours possible de lire ces quatre bits avec une seule instruction (MOVEW), seul l'état des bits "gauche" et "droite" est directement exploitable : il faudra d'abord masquer par un EOR l'état des bits "haut" et 'bas" avant que ce pouvoir prendre leur valeur en compte.

De fait, lorsque que l'on commence à s'intéresser à la chose, la première routine que l'on était ressemble souvent à celle publiée dans "La Bible De L'Amiga" :

assembleur

Cette routine retourne deux valeurs, dans les registres D0 et D1, indiquant respectivement l'état horizontal et l'état vertical de la manette : -1 signifie que la manette est à gauche (resp. en haut), 0 qu'il est au centre, et 1 qu'il est à droite (resp. en bas). A charge ensuite du programme appelant, de faire ce qu'il convient de ces valeurs.

Ainsi écrite, cette routine fait ce qu'on attend d'elle, mais n'est pas réellement très efficace. En tout cas, vue sa conception, elle serait beaucoup mieux si elle allait piocher dans une table les valeurs correctes : on réduirait ainsi le nombre de tests et de branchements, ce qui ferait gagner autant d'octets et de cycles. On diminurait également le décalage à droite d'un bit et le masquage par EOR, devenus superflus.

Le problème maintenant est de savoir de quelle manière organiser nos quatre bits pour en faire un index correct pour piocher dans la table ; pour cela, rappelons qu'une lecture de JOY0DAT ou JOY1DAT donne les valeurs suivantes ('G' = gauche, 'H' = haut, 'D'= droite, 'B' = bas, et 'x' indique un bit sans intérêt) :

xxxxxxGHxxxxxxDB

Après plusieurs tests, il apparaît que la manière la plus probante est la suivante :

xxxxxxGHDBxxxxxx

...qui s'obtient très facilement par une rotation de deux bits vers la droite de l'octet inférieur. Il ne reste plus qu'à décaler le mot entier de six bits vers la droite, pour obtenir un index valable, de la forme :

xxxxxxxxxxxxGHDB

En étudiant tous les cas avec un débogueur, on trouve les valeurs possibles suivantes :

assembleur

Notre table aura donc l'allure que voici (un 'X' indique une valeur non utilisée, par exemple l'impossible combinaison HBG) :

assembleur

Cette table peut être un rien optimisée, par exemple en omettant les deux 'X' finaux de change ligne (8 octets de gagnés) et en utilisant des valeurs sur des octets plutôt que des mots (50% de gagné !). Toutefois, je préfère utiliser des mots, étant donné que dans un jeu, les coordonnées des sprites sont souvent codées sur des mots. Ainsi, dans le programme principal, je n'ai plus qu'à écrire :

assembleur

...pour que les coordonnées de mon sprite soient actualisées en fonction de la position de la manette.

Il ne nous reste donc maintenant plus qu'à écrire la version finale de notre routine de lecture des manettes. Vous remarquerez que je décale le quartet GHDB de cinq bits et non de six, comme annoncé plus haut ; c'est simplement parce que j'accède à une table de mots. Les deux instructions :

assembleur

...équivalent en fait aux trois suivantes :

assembleur

...mais sont bien entendues plus courtes et plus rapides. Dans le même ordre d'idées, je lis d'abord la valeur de d1, afin de ne pas modifier d0, qui sert toujours d'index dans l'accès à la table des valeurs en X.

Notez enfin que cette routine n'est prévue que pour le port manette 1 de l'Amiga (la configuration standard de l'utilisateur voulant que la souris soit branchée dans le port 0 et la manette dans le port 1). Pour gérer une manette branchée sur le port 0 (par exemple, dans un jeu à deux joueurs), il suffit de remplacer $dff00c (JOY1DAT) par $dff00a (JOY0DAT) le reste est strictement identique.

assembleur

Conclusion

Mine de rien, on gagne beaucoup à essayer d'améliorer des routines à priori secondaires. Dans ce cas précis, on est passé d'une routine de près de 30 lignes, à une d'à peine 10. La vitesse d'exécution s'en est trouvée considérable multipliée et on s'en sort avec la satisfaction personnelle d'avoir quasiment atteint la perfection. Ce qui est loin d'être désagréable, au niveau de l'ego.

; ************************************
; * Illustration de  la  routine  de *
; * lecture des joysticks.  Lit   le *
; * joystick connecté au  GAMEPORT 1 *
; * et affiche son état.             *
; ************************************
; *  © S. Schreiber pour ANT - 1991  *
; ************************************

	incdir	"include:"
	include	"libraries/dos.i"
	include	"hardware/custom.i"

	include	"exec/exec_lib.i"
	include	"libraries/dos_lib.i"

	include	"misc/easystart.i"	; pour le Workbench startup

; ************************************
DEFSTR	MACRO
	dc.b	.2-.1	; longueur de la chaine
.1	dc.b	\1	; la chaine elle-même
	IFNC	'\2',''	; si \2 n'est pas vide...
	dc.b	\2	; alors mettre \2 aussi
	ENDC
.2	even		; alignement
	ENDM

custom	EQU	$dff000

; ************************************
Start	lea	dosname(pc),a1
	moveq	#33,d0
	CALLEXEC OpenLibrary
	move.l	d0,_DOSBase
	beq	NoDos

	move.l	#conname,d1
	move.l	#MODE_OLDFILE,d2
	CALLDOS	Open
	move.l	d0,_stdout
	beq	NoCon

; ************************************
TheLoop	moveq	#joy1dat,d0	; test du joystick 1
	bsr	Joy
	move.w	d0,d4	; sauve d0

	moveq	#0,d7	; flag : imprimer LF si <> 0

; *****	Affiche l'état de l'axe vertical
	addq.w	#1,d1	; 0 = haut, 1 = milieu, 2 = bas
	lsl.w	#2,d1
	lea	tabmsg1(pc),a0
	move.l	(a0,d1.w),d0
	beq.s	.1
	movea.l	d0,a0
	bsr	Print
	addq.w	#1,d7

; *****	Affiche l'état de l'axe horizontal
.1	addq.w	#1,d4	; 0 = gauche, 1 = milieu, 2 = droite
	lsl.w	#2,d4
	lea	tabmsg2(pc),a0
	move.l	(a0,d4.w),d0
	beq.s	.2
	movea.l	d0,a0
	bsr	Print
	addq.w	#1,d7

; *****	Au besoin, passe à la ligne
.2	tst.w	d7
	beq.s	.3
	lea	lfmsg(pc),a0
	bsr	Print

; *****	Petit delai pour être 'amiga friendly'
.3	moveq	#5,d1
	CALLDOS	Delay

; *****	Fin avec le bouton de feu du joystick
	btst	#7,$bfe001
	bne.s	TheLoop

; ************************************
Ciao	move.l	_stdout(pc),d1
	CALLDOS	Close

NoCon	movea.l	_DOSBase(pc),a1
	CALLEXEC CloseLibrary

NoDos	moveq	#0,d0
	rts

; ************************************
Joy	lea	custom,a0
	move.w	(a0,d0.w),d0
	ror.b	#2,d0
	lsr.w	#5,d0
	andi.w	#%11110,d0
	move.w	JoyTabY(pc,d0.w),d1
	move.w	JoyTabX(pc,d0.w),d0
	rts

JoyTabY	dc.w	0,1,1,0,-1,0,0,-1,-1,0,0,0,0,1,0,0
JoyTabX	dc.w	0,0,1,1,0,0,0,1,-1,0,0,0,-1,-1,0,0

; ************************************
Print	moveq	#0,d3
	move.b	(a0)+,d3
	move.l	a0,d2
	move.l	_stdout(pc),d1
	CALLDOS	Write
	rts

; ************************************
_DOSBase dc.l	0
_stdout	dc.l	0
dosname	dc.b	"dos.library",0
	even
conname	dc.b	"CON:0/11/640/200/JoyTest - par S. Schreiber",0
	even

tabmsg1	dc.l	hmsg,0,bmsg
tabmsg2	dc.l	gmsg,0,dmsg

; ************************************
gmsg	DEFSTR	<"gauche ">
dmsg	DEFSTR	<"droite ">
hmsg	DEFSTR	<"haut ">
bmsg	DEFSTR	<"bas ">
lfmsg	DEFSTR	1,$0a	; Line Feed

; ************************************
	END



[Retour en haut] / [Retour aux articles]