Suivez-nous sur X
|
|
|
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,
ALL
|
|
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
|
|
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
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : Assembleur - Le drapeau (ondulation d'un logo)
(Article écrit par Jérôme Étienne et extrait d'Amiga News Tech - mai 1992)
|
|
Comme en ce moment, je souffre d'un sérieux manque d'inspiration (l'angoisse du créateur...), j'ai choisi dans
les démos que je possède le premier effet que je n'avais pas encore réalisé...
Il se trouve que ce fut un drapeau. Le seul problème qui peut se poser dans ce programme est de savoir comment
faire l'effet d'ondulation. Personnellement, j'ai procédé avec des sinusoïdes, une en x et une en y, le cumule
des deux donnant l'effet désiré.
Du côté purement technique, il faut faire attention au fait que le logo qui sera affiché est large de 32 points
et haut de 12, soit 352 points au total. Vu que tout doit s'afficher en une VBL, il faut trouver deux
ou trois astuces simples et ne pas tout programmer directement.
Dans un premier temps, la courbe est précalculée, ce qui fait gagner un maximum de temps. Pour
cela, un petit programme GFA construit une table de sinus en ASCII. Cette table doit être
introduite juste après l'étiquette "SIN_TAB:". Elle sera modifiée par la routine "precompute_tab".
Elle ne fait que multiplier chaque valeur par la valeur de "RAY_FLAG" et la remettre au
même endroit (en écrasant donc le sinus). Pour ne pas provoquer d'erreur due à la destruction
de la table des sinus, je mets un drapeau nommé "precomputeflag".
Dans un second temps, l'effacement de l'écran se fait de la même manière que pour les
étoiles 3D publiées précédemment : au moment d'afficher
les points, je sauvegarde l'adresse de l'octet de destination dans une table. Puis avec une
autre routine, je lis cette table et j'efface tous les octets qui ont été inscrits. Le
tout mêlé avec un léger double tampon mémoire de tableaux pour aller avec celui des écrans, et
on obtient une routine relativement efficace pour effacer les points.
Dans un troisième temps, pour tracer les points, on ruse un peu avec les plans en profitant
du fait que le fond de l'écran est vide et qu'aucun des points ne se superpose.
Ces deux conditions permettent d'utiliser la technique appelée officieusement "un plan par
couleur" : ainsi, dans notre cas, on a besoin de deux couleurs donc on initialise deux plans de bits.
Pour tracer en couleur 1, on trace dans le plan de bits 1 sans effacer dans le plan de bits 2 comme
il aurait fallu le faire normalement. Cela permet de gagner du temps à l'affichage et à l'effacement.
La phrase du mois, qui est un aphorisme dosadi : "où la souffrance domine, la douleur atroce
est parfois un précieux pédagogue".
* TITRE: flag
* AUTEUR: j.etienne
* SUJET: ondulation d'un logo (drapeau) en point
* ASSEMBLEUR: devpac 2.14
incdir 'devpac:include/'
include 'exec/exec_lib.i'
include 'hardware/custom.i'
Custom = $dff000
execbase = 4
* define for screen
BPL_X = 320
BPL_Y = 200
BPL_DEPTH = 2
BPL_WIDTH = BPL_X/8
BPL_SIZE = BPL_WIDTH*BPL_Y
SCR_SIZE = BPL_SIZE*BPL_DEPTH
* define for flag
FLAG_WIDTH = 32
FLAG_HEIGHT = 12
NB_POINT = FLAG_WIDTH*FLAG_HEIGHT
RAY_FLAG = 10
VSYNC: macro
.wait_vsync\@:
move.l vposr(a5),d0
and.l #$1ff00,d0
cmp.l #\1*$100,d0
bne.s .wait_vsync\@
endm
WAIT_BLT: macro
lea CUSTOM,a5
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 #(BPL_DEPTH<<12)+$200,bplcon0(a5)
clr.w bplcon1(a5)
clr.w bplcon2(a5)
move.w #BPL_WIDTH*(BPL_DEPTH-1),bpl1mod(a5)
move.w #BPL_WIDTH*(BPL_DEPTH-1),bpl2mod(a5)
move.w #$2981,diwstrt(a5) *\
move.w #$f1c1,diwstop(a5) * > init un ecran 320*256
move.w #$0038,ddfstrt(a5) * >
move.w #$00d0,ddfstop(a5) */
bsr BUILD_COPLIST
move.l COPLIST_ADR(pc),cop1lc(a5) * > run my coplist
clr.w copjmp1(a5) */
move.w #$83C0,dmacon(a5) * dma blitter,copper & bitplane on
* init the cmap
move.w #$000,color+0*2(a5)
move.w #$0FF,color+1*2(a5)
move.w #$F00,color+2*2(a5)
move.w #$0F0,color+3*2(a5)
bsr PRECOMPUTE_TAB
MAIN_LOOP:
VSYNC $f
bsr BUILD_COPLIST
* double buffering for tab
move.l LOG_TAB_ADR_PT,d0
move.l PHY_TAB_ADR_PT,LOG_TAB_ADR_PT
move.l d0,PHY_TAB_ADR_PT
* double buffering for screen
move.l LOG_SCR_ADR,d0
move.l PHY_SCR_ADR,LOG_SCR_ADR
move.l d0,PHY_SCR_ADR
bsr CLR_SCR
bsr DRAW_FLAG
btst #6,$bfe001
bne MAIN_LOOP
bra INIT_END
CLR_SCR: *******************************************************
* this routine clears all the old points which were on this screen
move.l LOG_TAB_ADR_PT(pc),a0
tst.l (a0) *\ dont clear the page before
beq.s .END_CLEAR */ the first stars
move.l #NB_POINT-1,d0
moveq #0,d1
.LOOP_CLEAR:
move.l (a0)+,a1
move.b d1,(a1)
dbf d0,.LOOP_CLEAR
.END_CLEAR
rts
**************************************************** END_CLEAR_SCR
PRECOMPUTE_TAB: ***********************************************
tst.w PRECOMPUTE_FLAG
bne.s .END
move.w #-1,PRECOMPUTE_FLAG
lea SIN_TAB(pc),a0
move.w #$200-1,d0
.LOOP
move.w (a0),d1
muls #RAY_FLAG,d1
add.l d1,d1
swap d1
move.w d1,(a0)+
dbf d0,.LOOP
.END
rts
PRECOMPUTE_FLAG: dc.w 0
******************************************** END_PRECOMPUTE_TAB
DRAW_FLAG: ***********************************************************
lea FLAG_PICTURE(pc),a1
move.l LOG_TAB_ADR_PT(pc),a2
move.l ADR_Y(pc),a3
add.l SPD1_Y(pc),a3
cmp.l #SIN_TAB+$200*2,a3
blt.s .ADR_Y_LT_SIN_TAB
sub.l #$200*2,a3
.ADR_Y_LT_SIN_TAB
move.l a3,ADR_Y
move.l ADR_X(pc),a4
add.l SPD1_X(pc),a4
cmp.l #SIN_TAB+$200*2,a4
blt.s .ADR_X_LT_SIN_TAB
sub.l #$200*2,a4
.ADR_X_LT_SIN_TAB
move.l a4,ADR_X
move.l ADR_X(pc),a4
move.w OY(pc),d6
move.w #FLAG_HEIGHT-1,d4
.LOOP_EACH_LINE
move.l ADR_Y(pc),a3
move.w OX(pc),d5
moveq #FLAG_WIDTH-1,d3
.LOOP_EACH_POINT
move.w d5,d0
add.w (a4),d0
move.w d6,d1
add.w (a3),d1
move.b (a1)+,d2
bsr POINT
add.w DX(pc),d5
add.l SPD2_Y(pc),a3
cmp.l #SIN_TAB+$200*2,a3
blt.s .A3_LT_SIN_TAB
sub.l #$200*2,a3
.A3_LT_SIN_TAB
dbf d3,.LOOP_EACH_POINT
add.l SPD2_X(pc),a4
cmp.l #SIN_TAB+$200*2,a4
blt.s .A4_LT_SIN_TAB
sub.l #$200*2,a4
.A4_LT_SIN_TAB
add.w DY(pc),d6
dbf d4,.LOOP_EACH_LINE
rts
* toutes les vitesses doivent etre indiquees en chiffre paire
ADR_X: dc.l SIN_TAB
SPD1_X: dc.l 20
SPD2_X: dc.l 40
ADR_Y: dc.l SIN_TAB
SPD1_Y: dc.l 20
SPD2_Y: dc.l 50
DX: dc.w 8
DY: dc.w 12
OX: dc.w 30
OY: dc.w 30
******************************************************** END_DRAW_FLAG
POINT: **************************************************************
* in: d0.w = x
* d1.w = y
* d2.b = color
* out: none
* detroyed: d0/d1/a0
move.l LOG_SCR_ADR(pc),a0
lsl.l #2,d1
add.l ADR_LINE_ACCORDING_TO_Y(pc,d1.w),a0
move.w d0,d1
lsr.w #3,d1
lea (a0,d1.w),a0
and.w #%111,d0
neg.w d0
addq.w #7,d0
cmp.b #1,d2
beq.s .OTHER_COLOR
move.l a0,(a2)+
bset d0,(a0)
rts
.OTHER_COLOR
lea BPL_WIDTH(a0),a0
move.l a0,(a2)+
bset d0,(a0)
rts
********************************************************** END_POINT
ADR_LINE_ACCORDING_TO_Y:
DUMMY set 0
rept BPL_Y
dc.l DUMMY
DUMMY set DUMMY+BPL_WIDTH*BPL_DEPTH
endr
INIT_END: *********************************************************
* reactivation de l'ancienne coplist
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
* et on retourne d'ou l'on vient.
moveq #0,d0 * flag d'erreur desactive
rts
GfxName: dc.b "graphics.library",0
EVEN
******************************************************* end_INIT_END
BUILD_COPLIST: ********************************************************
move.l COPLIST_ADR,a0
move.l PHY_SCR_ADR,d2
moveq #BPL_DEPTH-1,d0
move.w #bplpt,d1
.LOOP_INIT_BPL_IN_CLIST
move.w d1,(a0)+
addq.l #2,d1
swap d2
move.w d2,(a0)+
swap d2
move.w d1,(a0)+
addq.l #2,d1
move.w d2,(a0)+
add.l #BPL_WIDTH,d2
dbf d0,.LOOP_INIT_BPL_IN_CLIST
move.l #$fffffffe,(a0)+ * montre la fin de la clist
rts
********************************************************* END_BUILD_COPLIST
FLAG_PICTURE:
dc.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
dc.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
dc.b 1,1,1,1,2,2,2,2,1,1,1,1,2,2,1,1,1,1,2,2,1,1,2,2,2,2,2,2,2,2,1,1
dc.b 1,1,1,2,2,2,2,2,2,1,1,1,2,2,2,1,1,1,2,2,1,1,2,2,2,2,2,2,2,2,1,1
dc.b 1,1,2,2,1,1,1,1,2,2,1,1,2,2,2,2,1,1,2,2,1,1,1,1,1,2,2,1,1,1,1,1
dc.b 1,1,2,2,1,1,1,1,2,2,1,1,2,2,1,2,2,1,2,2,1,1,1,1,1,2,2,1,1,1,1,1
dc.b 1,1,2,2,2,2,2,2,2,2,1,1,2,2,1,1,2,2,2,2,1,1,1,1,1,2,2,1,1,1,1,1
dc.b 1,1,2,2,2,2,2,2,2,2,1,1,2,2,1,1,1,2,2,2,1,1,1,1,1,2,2,1,1,1,1,1
dc.b 1,1,2,2,1,1,1,1,2,2,1,1,2,2,1,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,1,1
dc.b 1,1,2,2,1,1,1,1,2,2,1,1,2,2,1,1,1,1,1,2,1,1,1,1,1,2,2,1,1,1,1,1
dc.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
dc.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
******** datas
* variables
LOG_TAB_ADR_PT: dc.l TAB_ADR_PT_1
PHY_TAB_ADR_PT: dc.l TAB_ADR_PT_2
TAB_ADR_PT_1: ds.l NB_POINT
TAB_ADR_PT_2: ds.l NB_POINT
LOG_SCR_ADR: dc.l ecran1
PHY_SCR_ADR: dc.l ecran2
COPLIST_ADR: dc.l coplist
SIN_TAB: include 'Ram:sin_tab.dat'
section ZONE_CHIP,BSS_C
ecran1: ds.l (SCR_SIZE*2)/4
ecran2: ds.l (SCR_SIZE*2)/4
coplist: ds.l 100
end
|
Listing 2 : Makesinus.GFA
OPEN "O",#1,"ram:sin_tab.dat"
FOR i=0 TO 512-1 STEP 8
FOR j=0 TO 7
n=SIN((i+j)*PI/256)
IF j=0
PRINT #1,CHR$(9)+"dc.w"+CHR$(9);
ELSE
PRINT #1,",";
ENDIF
IF n=1
n=0.9999999
ENDIF
PRINT #1,"$";HEX$(INT(n*32768),4);
NEXT j
PRINT #1,CHR$(10);
NEXT i
CLOSE #1
END
|
|