Voilà du code qui marche
Quant au VBLANK, j'ai fait une petite routine waitVBlank pour faire juste ça, mais je crois qu'il serait mieux de réorganiser le code un peu pour qu'il y ait une partie seulement qui affiche à l'écran. J'aimerais bien pouvoir tester ces programmes sur une vraie GBA, parfois j'ai l'impression que l'émulation n'est pas parfaite... A propos, il fallait deux vélocités (une X et une Y), et j'ai trouvé que les drapeaux avec les soustractions sont un peu confus, le drapeau carry est armé quand le résultat ne prend pas un "borrow" (je suppose que ça veux dire, si le résultat > 0) et désarmé quand il y'en a (le résultat <= 0), mais j'en suis pas sûr.
.arm
.include "gba.inc"
SCREEN_W = 240
SCREEN_H = 160
PADDLE_X = SCREEN_W/2-(3*8)/2
PADDLE_Y = SCREEN_H-8
BALL_X = 0
BALL_Y = 0
.text
.global main
main:
ldr r0,=OAM @ on reset les sprites (je ne sais pas si ça a vraiment de l'importance)
ldr r1,=128 @ il y a 128 emplacements de 8 octets chacuns (l'OAM fait 1ko)
ldr r2,=(300<<16) @ le 3ème octet suivit du prochain bit définit la coordonnée X (2^9=512 valeurs) du sprite,
@ on la met donc à 300 pour être hors de l'écran (il fait 240*160)
@ (pour les attributs de l'OAM, cf http://gfx.developpez.com/prog-gba/touches/#L8 )
reset_sprites_loop:
str r2,[r0],#8 @ on colle la valeur de r2 à l'adresse de r0, puis incrémente de 8 octets l'adresse de r0
subs r1,r1,#1 @ la boucle fait 128 tours
bne reset_sprites_loop
ldr r1,=REG_DISPCNT
ldr r2,=(MODE_0|BG2_ENABLE|OBJ_ENABLE|OBJ_MAP_1D)
str r2,[r1]
ldr r0,=OAM @ on va s'occuper de charger nos sprites
ldr r1,=(SQUARE|COLOR_16|PADDLE_Y)|((SIZE_8|PADDLE_X)<<16) @ cf l'organisation des attributs des sprites (là on règle les deux premiers)
mov r2,#0 @ premier tile de 8*8 pixels du sprite (index du sprite dans le CHARMEM quoi)
str r1,[r0],#4 @ on charge les deux premiers attributs, puis on les "saute"
str r2,[r0],#4 @ on charge le troisième attribut
ldr r1,=(SQUARE|COLOR_16|PADDLE_Y)|((SIZE_8|PADDLE_X+8)<<16)
mov r2,#1
str r1,[r0],#4
str r2,[r0],#4
ldr r1,=(SQUARE|COLOR_16|PADDLE_Y)|((SIZE_8|PADDLE_X+16)<<16)
mov r2,#2
str r1,[r0],#4
str r2,[r0],#4
ldr r1,=(SQUARE|COLOR_16|BALL_Y)|((SIZE_8|BALL_X)<<16)
mov r2,#3 @ quatrième tile
str r1,[r0],#4
str r2,[r0],#4
ldr r1,=OBJPAL @ on s'occupe de la palette maintenant
ldr r2,=5 @ nombre de couleurs de la palette à copier
ldr r3,=palette
palette_loop:
ldr r7,[r3],#4 @ on charge la valeur à l'adresse de r3 dans r7, puis on incrémente de 4 octets (16 bits = 1 couleur) l'adresse de r3
str r7,[r1],#4 @ on colle le tout dans r1 puis incrémente de même r1
subs r2,r2,#1 @ on fait 5 tours
bne palette_loop
ldr r1,=CHARMEM @ au tour des sprites
ldr r2,=8*8*4 @ tailles des sprites et nombre
ldr r3,=paddle_left
sprite_loop:
ldr r7,[r3],#4 @ la même qu'au dessus
str r7,[r1],#4
subs r2,r2,#1
bne sprite_loop
main_loop:
mov r3,#KEYS_HIGH @ MSB
orr r3,r3,#KEYS_LOW @ ajouter LSB de l'adresse (plus rapide que ldr r3,#KEYS)
mov r2,#0x300
orr r2,#0xFF @ r2 = $3FF (10 touches codés sur 10 bits)
ldr r4,[r3] @ r4 = touche pressée
ldr r0,=player_x
tst r4, #KEY_LEFT
bleq left
tst r4, #KEY_RIGHT
bleq right
ldr r6,=REG_VCOUNT
waitVBlank:
ldrb r7,[r6]
cmp r7,#161
bne waitVBlank
ldrb r0,[r0] @ on charge un octet de l'adresse r0 dans r0
ldr r3,=OAM+2 @ deuxième attribut (=OAM+2 octets), X=1er octet+1er bit suivant
ldrh r4,[r3]
and r4,r4,#0xFE00 @ on récupère donc les 9 premiers bits
add r4,r0
strh r4,[r3]
add r4,#8 @ on s'occupe de la deuxième partie de la raquette (centre)
strh r4,[r3, #8] @ on colle le tout dans l'emplacement suivant (8 octets après)
add r4,#8 @ idem avec la troisième partie
strh r4,[r3, #16]
bl handle_ball @ on s'occupe de la balle
mov r0,#0x100 @ pour ralentir le programme
delay_loop:
subs r0,r0,#1
bne delay_loop
b main_loop
left:
ldrb r2,[r0]
subs r2,r2,#1
bxcc lr @ on quitte si le carry flag est set (donc le résultat du dessus inférieur à 0)
strb r2,[r0] @ sauver les nouvelles coordonnées (1 octet)
bx lr @ quitter la routine
right:
ldrb r2,[r0]
add r2,r2,#1
cmp r2,#SCREEN_W-(8*3) @ on test voir si ça sort de l'écran
bxcs lr @ on quitte si le sign flag est mis
strb r2,[r0]
bx lr
handle_ball: @ le code suivant doit incrémenter ou décrementer X et Y en fonction de la direction de la balle (gère les rebonds), mais ça bug :/
@ r0 = nouveau valeur de ball_x
@ r2 = ball_x (ptr)
@ r3 = ball_vel_x (ptr)
@ r4 = ball_vel_x (valeur)
ldr r2,=ball_x
ldrb r0,[r2]
ldr r3,=ball_velocity_x
ldrb r4,[r3]
add r0,r0,r4 @ ball_x + ball_vel
and r0,r0,#0xFF @ si le résultat est plus de 8 bits
stmfd sp!,{lr} @ pour faire des appels imbriqués
@ blcc change_ball_velocity
cmp r0,#SCREEN_W-8
blcs change_ball_velocity
ldmfd sp!,{lr}
strb r0,[r2]
ldr r2,=ball_y
ldrb r1,[r2]
ldr r3,=ball_velocity_y
ldr r4,[r3]
add r1,r1,r4
and r1,r1,#0xFF
stmfd sp!,{lr}
@ blcc change_ball_velocity
cmp r1,#SCREEN_H-8
blcs change_ball_velocity
ldmfd sp!,{lr}
strb r1,[r2]
ldr r3,=OAM+3*8
ldrh r4,[r3]
ldrh r5,[r3,#2]
and r4,r4,#0xFF00
add r4,r1
strh r4,[r3],#2
and r5,r5,#0xFE00
add r5,r0
strh r5,[r3]
bx lr
change_ball_velocity:
eor r4,#0xFF
add r4,#1
strb r4,[r3]
bx lr
.ltorg
palette:
.hword 0x0000,0x001F,0x56B5,0x7FFF
.align 4 @ peut être inutile maintenant ?
paddle_left:
.word 0x00000000
.word 0x22011000
.word 0x22011130
.word 0x33033133
.word 0x22011333
.word 0x22011133
.word 0x22011130
.word 0x22011000
paddle_center:
.word 0x00000000
.word 0x22222222
.word 0x22222222
.word 0x33333333
.word 0x22222222
.word 0x22222222
.word 0x22222222
.word 0x22222222
paddle_right:
.word 0x00000000
.word 0x00011022
.word 0x03111022
.word 0x33133033
.word 0x33311022
.word 0x33111022
.word 0x03111022
.word 0x00011022
ball:
.word 0x00003330
.word 0x00033333
.word 0x00033333
.word 0x00033333
.word 0x00003330
.word 0x00000000
.word 0x00000000
.word 0x00000000
.data @ ne faudrait-il pas que je le mette avant les sprites ?
player_x:
.byte PADDLE_X
ball_x:
.byte BALL_X
ball_y:
.byte BALL_Y
ball_velocity_x:
.byte 1
ball_velocity_y:
.byte 1
EDIT :
En effet, le carry agit différemment pour les instructions add et sub/cmp. Pour les add c'est normal, pour les sub/cmp, z80 c = cc (carry clear) et nc = cs (carry set), c'est le contraire de ce que l'on penserait... c'est bizarre.