Obligement - L'Amiga au maximum

Dimanche 21 juillet 2019 - 19:05  

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 - Trial Playfield
(Article écrit par Jérôme Étienne et extrait d'Amiga News Tech - octobre 1991)


Voici un titre pour le moins alléchant, qui a été imaginé dans le but d'attirer le lecteur et le forcer à lire cet article, même contre sa propre volonté.

Un article que j'ai écrit à la sueur de mon front, sous le soleil qui commence à taper si fort qu'il dérègle ces trois neurones déprimés d'avoir échoué dans mon crâne bouillonnant... Bon, sérieusement, je vais tenter de vous expliquer comment obtenir un pseudo trial-playfield, c'est-à-dire trois plans totalement indépendants les uns des autres. Vous connaissez déjà les possibilités de deux de ces trois plans, qui sont ceux décrits dans toutes les documentations, au chapître Dual Playfield. Mais je vais quand même vous en faire un petit résumé.

1 + 1 = 2

La gestion de chaque playfield est séparée en ce qui concerne la taille et le défilement, mais pas la couleur. En effet, l'Amiga n'a, à ma connaissance, qu'un seul registre permettant d'indiquer à la machine le nombre de bitplans de l'écran (il s'agit bien sûr de BPLCON0). Or, ayant deux playfields et un seul compteur de bitplans, la machine tranche le problème de la manière suivante : si le nombre de bitplans est pair, les deux playfields auront la même quantité de plans. Dans le cas contraire, c'est le playfield 1 qui bénéficiera du bitplan supplémentaire.

Et de trois !

Pour en revenir au fameux troisième playfield, celui-ci n'étant pas "officiel", il est bien moins souple et ne permet que le monochrome. De plus, les défilements verticaux et horizontaux sont plus compliqués à programmer que les défilements normaux.

Il est entièrement composé de sprites.

- "Mais... mais... comment fait-il ? Les documentations que nous avons lues affirment que l'on ne peut pas afficher plus de 8 sprites sur une même ligne de raster !" crie la foule d'une seule voix. Et moi de surenchérir :

- "J'irais même plus loin, en affirmant qu'il n'est composé que d'un seul sprite", tout fier d'avoir enfin quelqu'un qui m'écoute, qui me fait momentanément oublier que je ne suis qu'une poussière au milieu de ce grand tout que représente l'Univers. La technique est très simple, en fait ; elle fait beaucoup intervenir le Copper et les sprites.

Voyage au pays des sprites

Comme vous le savez sûrement, le procédé habituel pour se servir des sprites est de faire pointer les canaux DMA adéquats (SPRxPT) sur une partie de la mémoire Chip où l'on aura préalablement placé les données du sprite. Rappel : ces données indiquent sa position (SPRxPOS et SPRxCTL) ainsi que l'image du sprite elle-même (SPRxDATA et SPRxDATB).

Pour que le sprite apparaisse à l'écran, il faut aussi autoriser le DMA sprite en mettant à 1 le bit concerné (bit SPREN dans DMACON). Dans le listing qui suit cet article, une chose saute aux yeux et les mord violemment : le DMA sprite n'est pas autorisé ! En effet, et c'est là tout le secret, j'utilise le mode dit manuel des sprites, c'est-à-dire que je charge le Copper de faire le travail du DMA sprite, travail qui consiste à mettre la position et l'image (ce terme me paraît légèrement exagéré d'un seul coup car en fait, il s'agit un seul et unique mot de 16 petits bits) la position et l'image du sprite, disais-je donc, dans les registres prévus à cet effet. Pour obtenir un playfield continu, il faut renouveler le sprite tout les 16 pixels. J'effectue cette operation ô combien délicate avec l'aide précieuse du Copper. Comme chacun sait, chaque instruction Copper prend un temps machine équivalent à la durée d'affichage de 8 pixels en basse résolution ; donc, la douloureuse vérité s'impose : on doit renouveler le sprite en ne changeant que deux registres au maximum. Ce fut pénible, mais cela devait être écrit.

Le problème vient du fait que d'un côté, les sprites sont caractérisés par quatre registres (SPRxPOS, SPRxCTL, SPRxDATA et SPRxDATB) et que de l'autre côté, on ne peut en changer que deux. Pour contourner cela, on peut facilement arrêter d'utiliser SPRxDATB et donc se contraindre à avoir un sprite monochrome. On remarque aussi que SPRxCTL reste le même durant toute la longueur de la ligne de raster. Donc, si on ne le modifie qu'en début de ligne, il ne nous reste plus, ô miracle, que deux registres à bidouiller, à savoir SPRxPOS et SPRxDATA.

Concrètement

La routine build_coplist, qui construit - comme son nom l'indique - une liste Copper capable de réaliser toutes les merveilles dont je viens de vous parler, procède ainsi : à chaque début de ligne, on initialise SPRxCTL (qui sera constant pendant toute la ligne) avec le numéro de la ligne actuelle plus 1, puis on attend avec un Wait aproprié que le rayon atteigne le bord gauche de l'écran et on commence la succession de SPRxPOS et SPRxDATA (20 de chaque en tout). Et ainsi de suite pour toutes les lignes.

Maintenant que vous connaissez le principe du pseudo troisième playfield, je vais vous expliquer comment on peut faire des défilements dessus. Déjà, les techniques simples et habituelles tel que faire bouger un pointeur sur un bitplan plus grand que l'écran ne sont pas utilisables, car toutes les positions des sprites (registre : SPRxPOS) sont absolues, donc changer un pointeur ne donnerait rien de très intéressant. Résultat, l'unique méthode de défilement que je connaisse s'adaptant à ce cas se résume à un grand coup de Blitter, ce qui permet de faire un défilement vertical très facilement. Pour ce qui est du défilement horizontal, c'est plus ardu.

Dans le cas particulier (et rare) où le pas du défilement est de 16 pixels, on peut encore utiliser un déplacement de mémoire simple à l'aide du Blitter. Pour le cas d'un pas inférieur à 16 pixels, il faut encore utiliser le Blitter mais cette fois-ci beaucoup plus finement, en se servant du fait que ce qui, sort d'une ligne, à cause du glissement, reparaît sur le début de la ligne suivante.

Pour être honnête, je ne suis pas du tout l'inventeur de cette technique, que je connais grâce à une cartouche que je ne nommerais pas et qui me permet de décoder une liste Copper à n'importe quel moment d'un jeu ou autre, de la modifier et de reprendre le cours des choses... Elle a été utilisée dans des jeux tels que Turrican 2 ou SwitchBlade 2 pour afficher les scores en transparent. Le nom de l'auteur de la première routine m'est complètement inconnu, mais je le remercie ici publiquement.

** LISTING DE JÉROME ÉTIENNE POUR L'ANT
** sur le 'trial playfield'

	incdir	'include:'
	include	'exec/exec_lib.i'
	include	'hardware/custom.i'

custom		=	$dff000
execbase	=	4

plane_x		=	320
plane_y		=	200
plane_width_word	=	plane_x/16
plane_size	=	(plane_x/8)*plane_y

vsync:	macro
.wait_vsync\@:
	move.l	vposr(a5),d0
	and.l	#$1ff00,d0
	cmp.l	#$03000,d0
	bne.s	.wait_vsync\@
	endm

wait_blt:	macro
	btst	#14,dmaconr(a5)
.loop_wait_blt\@:
	btst	#14,dmaconr(a5)
	bne.s	.loop_wait_blt\@
	endm

******************************************************
**************  programme principal  *****************
******************************************************
	move.l	(execbase).w,a6
	lea	custom,a5

	CALLEXEC	Forbid
	move.w	#$03e0,dmacon(a5)	* all dma off except disk

	move.w	#$1200,bplcon0(a5)	* 1 SEUL bitplan
	clr.w	bplcon1(a5)
	clr.w	bplcon2(a5)		
	clr.w	bpl1mod(a5)
	clr.w	bpl2mod(a5)
	move.w	#$2981,diwstrt(a5)	* 320*200
	move.w	#$f1c1,diwstop(a5)
	move.w	#$0038,ddfstrt(a5)
	move.w	#$00d0,ddfstop(a5)


	bsr	build_coplist		
	
	move.l	coplist_adr,cop1lc(a5)	* > run my coplist
	clr.w	copjmp1(a5)		*/
	
	move.w	#$83c0,dmacon(a5)	* dma blitter,copper & bitplane on

main_loop:
	vsync

	wait_blt			*\
	clr.w	bltadat(a5)		* >-efface l'ecran a chaque vbl
	clr.w	bltamod(a5)		* > pour bien montrer que le
	move.w	#$ffff,bltafwm(a5)	* > playfield est dans le sprite
	move.w	#$ffff,bltalwm(a5)	* > et non dans le bitplan
	move.w	#$01f0,bltcon0(a5)	* >
	clr.w	bltcon1(a5)		* >
	clr.w	bltdmod(a5)		* >
	move.l	plane_adr,bltdpt(a5)	*/ 
	move.w	#plane_y*64+plane_width_word,bltsize(a5)
	
	move.b	$bfec01,d0	*\
	not	d0		* >capture the key wich is pressed
	ror.b	#1,d0		*/ and put is code RAW in d0
	cmp.b	#$45,d0		*\
	beq.s	init_end	*/ sort si on press sur esc
	
	btst	#6,$bfe001
	bne.s	main_loop

******** init end ***********
*	reactivation de l'old coplist
init_end:
	wait_blt
	lea	GfxName(pc),a1		* nom de la library ds a1
	moveq	#0,d0			* version 0 (the last)
	CALLEXEC	OpenLibrary	* lib graphique ouverte
	move.l	d0,a4			* adr de graphicbase ds a4
	move.l	38(a4),cop1lc(a5)	* chargement de l'adr de
	clr.w	copjmp1(a5)		* l'old coplist et lancement

	move.w	#$83e0,dmacon(a5)	* activation des canaux dma necessaires
	CALLEXEC	Permit		* multi switching autorise
	
fin:	moveq	#0,d0	* flag d'erreur desactive
	rts
GfxName:		dc.b	"graphics.library",0
	even
*******************************************
build_coplist:
	move.l	coplist_adr(pc),a0
	move.w	#bplpt,(a0)+		*\
	move.w	plane_adr(pc),(a0)+	* >init les pointeurs bitplans
	move.w	#bplpt+2,(a0)+		* >
	move.w	plane_adr+2(pc),(a0)+	*/
	lea	image,a1
	moveq	#$29,d0
.loop_chaque_ligne:
	move.w	#spr+sd_ctl,(a0)+	*\
	move.w	d0,d1			* >-init spr_ctl a la ligne juste
	lsl.w	#8,d1			* > superieure a la ligne actuelle
	and.w	#$ff00,d1		* >
	move.w	d1,(a0)			* >
	addq.w	#1,(a0)+		*/
	move.w	d0,d1			*\
	ror.l	#8,d1			* >-init le wait juste sur le bord 
	and.l	#$ff000000,d1		* > gauche de l'ecran
	or.l	#$0039fffe,d1		* >
	move.l	d1,(a0)+		*/ 
	move.w	d0,d1			*\
	lsl.w	#8,d1			* >-prepare le futur spr_pos
	and.w	#$ff00,d1		* >
	or.w	#$0040,d1		*/
	moveq	#20-1,d2		* 20= largeur de l'ecran /16
.loop_each_word:
	move.w	#spr+sd_pos,(a0)+	*\ init spr_pos	
	move.w	d1,(a0)+		*/
	move.w	#spr+sd_dataa,(a0)+	*\ init spr_data
	move.w	(a1)+,(a0)+		*/
	addq.w	#8,d1			*\-on calcul le prochain spr_pos et
	dbf	d2,.loop_each_word	*/ boucle pour le prochain mot
	addq.w	#1,d0			*\ -on teste si on est arrive sur la 
	cmp.w	#$f1,d0			* > ligne 200.Si oui, on a fini.
	blt.s	.loop_chaque_ligne	*/
	
	move.l	#$fffffffe,(a0)+	* montre la fin de la clist
	rts

******** datas
*	variables
plane_adr:	dc.l	ecran
coplist_adr:	dc.l	coplist

image_raw:	incbin	'fnt_32.bit'
image	=	image_raw+64
	section	ZONE_CHIP,BSS_C
ecran:		ds.l	plane_size/4
coplist:	ds.l	34000/4

	end

Note : une petite erreur s'est glissée dans le source. Voir cet article pour plus d'informations.

Le mois prochain, vous aurez dans cette rubrique probablement la technique de défilement la plus rapide possible (et en plus c'est vrai !). Il est en fait virtuellement impossible de faire mieux. Encore un algorithme que je n'ai pas trouvé, d'ailleurs. Son auteur est à ma connaissance Dino Dini, le génie qui a pondu Kick Off.


[Retour en haut] / [Retour aux articles]