Groupe 6 — Sprites Officiel
6,1 Sprite Reset · 6,2 Sprite Set · 6,3 Sprite Hide · 6,4 Sprite Collision · 6,5 Sprite Position
Un sprite est une image de la mémoire graphique (voir le groupe 5) affichée par-dessus l'écran sans l'abîmer : les sprites occupent les 4 bits hauts de chaque pixel, le fond les 4 bits bas. 5,36 lit la couche des sprites, 5,33 le fond.
6,2 place un sprite. Son numéro d'image est l'index de l'image (0 à 63) dans les sprites 16 × 16, ou dans les sprites 32 × 32 si l'on ajoute $40. La valeur $80 veut dire « inchangé », comme $8080 pour la position et $80 pour le retournement et l'ancre : on peut ainsi ne modifier qu'un réglage. NeoBASIC efface le bit 7 du numéro d'image, si bien que sprite n image $80 (la numérotation de 5,7) y désigne l'image 0 ; par l'appel direct, $80 sur un sprite neuf ne dessine rien (vérifié au banc).
L'ancre dit quel point du sprite se trouve aux coordonnées données : 0 le centre, puis 1 à 9 comme le pavé numérique (7 en haut à gauche, 5 au centre, 3 en bas à droite). La documentation du firmware parle d'un octet de drapeaux (32 bits) en P8 ; le code ne le lit pas, la taille vient du bit 6 du numéro d'image.
Les exemples chargent le fichier graphique du groupe 5 déclaré comme un sprite 16 × 16 (moitié gauche couleur 2, moitié droite couleur 5), et effacent les sprites (6,1) avant de rendre la main.
6,1 Sprite Reset Officiel
Efface tous les sprites et remet le système des sprites à zéro.
Entrées : aucune.
Sorties : aucune.
En NeoBASIC, sprite clear fait cet appel, de même que clear (donc run).
Mots-clés NeoBASIC qui font cet appel : clear, sprite
Texte de la documentation du firmware (anglais)
Reset the sprite system.
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static void xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
static uint8_t gfx[256 + 128]; /* en-tête + une image 16x16, 4 bits par pixel */
static void images(uint8_t genre) { /* 1 : une tuile ; 2 : un sprite 16x16 */
gfx[0] = 1;
gfx[genre] = 1;
for (uint8_t y = 0; y < 16; y++)
for (uint8_t i = 0; i < 8; i++)
gfx[256 + y * 8 + i] = i < 4 ? 0x22 : 0x55; /* gauche : couleur 2, droite : 5 */
neo_file_store("img.gfx", gfx, sizeof gfx);
neo_file_load("img.gfx", (void *)0xFFFF); /* $FFFF : mémoire graphique */
}
static uint8_t sprite_pixel(uint16_t x, uint16_t y) { /* 5,36 : couche des sprites */
libre();
xy(0, x, y);
api(5, 36);
return ControlPort.params[0];
}
/* Afficher un sprite, puis tout effacer (groupe 6, fonction 1). */
int main(void) {
images(2); /* un sprite 16x16 */
neo_sprite_set(0, 200, 170, 0, 0, 0); /* 6,2 : centré en (200, 170) */
uint8_t a = sprite_pixel(200, 170);
neo_sprite_reset(); /* Sprite Reset */
uint8_t b = sprite_pixel(200, 170);
printf("Avant : %u, apres : %u\n", a, b);
return 0;
}Avant : 5, apres : 0Mad Pascal
// Afficher un sprite, puis tout effacer (groupe 6, fonction 1).
program raz;
uses crt, neo6502;
var a, b: byte;
gfx: array[0..383] of byte; // en-tête + une image 16x16
procedure images(genre: byte); // 1 : une tuile ; 2 : un sprite 16x16
var y, i: byte;
begin
fillchar(@gfx, 384, 0);
gfx[0] := 1;
gfx[genre] := 1;
for y := 0 to 15 do
for i := 0 to 7 do
if i < 4 then gfx[256 + y * 8 + i] := $22 // gauche : couleur 2
else gfx[256 + y * 8 + i] := $55; // droite : couleur 5
NeoSave('img.gfx', word(@gfx), 384);
NeoLoad('img.gfx', $FFFF); // $FFFF : mémoire graphique
end;
begin
images(2); // un sprite 16x16
NeoUpdateSprite(0, 200, 170, 0, 0, 0); // 6,2 : centré en (200, 170)
a := NeoGetSpritePixel(200, 170);
NeoResetSprites; // Sprite Reset
b := NeoGetSpritePixel(200, 170);
writeln('Avant : ', a, ', apres : ', b);
end.Avant : 5, apres : 0NeoBASIC
10 ' Afficher un sprite, puis tout effacer (groupe 6, fonction 1)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 2, 1 : ' en-tete
22 for y = 0 to 15 : for i = 0 to 7 : c = $22 : if i > 3 then c = $55
24 poke d + 256 + y * 8 + i, c : next i : next y : ' gauche : couleur 2, droite : 5
26 save "img.gfx", d, 384 : load "img.gfx", $ffff : ' $ffff : memoire graphique
30 sprite 0 image 0 to 200,170
40 a = spoint(200,170)
50 sprite clear
60 b = spoint(200,170)
70 print "Avant : ";a;", apres : ";bAvant : 5, apres : 0Assembleur 65C02 (64tass)
; Afficher un sprite, puis tout effacer (groupe 6, fonction 1).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr images ; un sprite 16x16
stz ancre ; ancre 0 : centre
lda #200
ldy #170
jsr place
lda #200
ldy #170
jsr spixel
sta a
jsr efface ; fonction 1 : Sprite Reset
lda #200
ldy #170
jsr spixel
sta b
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Place le sprite 0 : X en A, Y en Y (inférieurs à 256), image 0, sans retournement, ancre dans ancre.
place: pha
jsr WaitMessage
pla
stz ControlPort+4 ; P0 : sprite 0
sta ControlPort+5 ; P1-P2 : X
stz ControlPort+6
sty ControlPort+7 ; P3-P4 : Y
stz ControlPort+8
stz ControlPort+9 ; P5 : image 0
stz ControlPort+10 ; P6 : pas de retournement
lda ancre
sta ControlPort+11 ; P7 : ancre
lda #6
ldx #2 ; 6,2 : Sprite Set
jmp appel
ancre: .byte 7
; Couleur de la couche des sprites en (A, Y), lue par 5,36, rendue dans A.
spixel: pha
jsr WaitMessage
pla
sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
lda #5
ldx #36 ; 5,36 : Read Sprite Pixel
jsr appel
lda ControlPort+4
rts
; Efface tous les sprites.
efface: jsr WaitMessage
lda #6
ldx #1 ; 6,1 : Sprite Reset
jmp appel
; Enregistre gfx dans img.gfx (3,3), puis le charge en mémoire graphique (3,2 vers $FFFF).
images: jsr WaitMessage
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #<gfx
sta ControlPort+6
lda #>gfx
sta ControlPort+7
lda #<384
sta ControlPort+8
lda #>384
sta ControlPort+9
lda #3
ldx #3 ; 3,3 : Save File
jsr appel
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #$FF
sta ControlPort+6 ; $FFFF : mémoire graphique
sta ControlPort+7
lda #3
ldx #2 ; 3,2 : Load File
jmp appel
nomgfx: .byte 7
.text "img.gfx"
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
gfx: .byte 1, 0, 1, 0 ; en-tête : un sprite 16x16
.fill 252
.rept 16 ; 16 lignes : gauche couleur 2, droite couleur 5
.byte $22, $22, $22, $22, $55, $55, $55, $55
.endrept
a: .byte 0
b: .byte 0
t0: .text "Avant : ", 0
t2: .text ", apres : ", 0Avant : 5, apres : 06,2 Sprite Set Officiel
Place ou modifie un sprite : position, image, retournement, ancre.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du sprite |
P1-P2 | uint16 | X ($8080 : inchangé) |
P3-P4 | uint16 | Y |
P5 | uint8 | image : 0-63 sprites 16×16, +$40 sprites 32×32 ; $80 : inchangée |
P6 | uint8 | retournement : bit 0 horizontal, bit 1 vertical ; $80 : inchangé |
P7 | uint8 | ancre 0 à 9 ; $80 : inchangée |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | 1 numéro de sprite ou ancre invalide, 2 image absente |
L'exemple place le sprite avec l'ancre 7 (son coin haut gauche en (200, 160)), puis ne change que le retournement : position $8080, image $80 et ancre $80 restent telles quelles, et les deux moitiés s'échangent. En NeoBASIC, sprite n image i anchor a flip f to x,y fait cet appel.
Mots-clés NeoBASIC qui font cet appel : sprite
Texte de la documentation du firmware (anglais)
Set or update the sprite specified in Parameter:0.
The parameters are : Sprite Number, X Low, X High, Y Low, Y High, Image, Flip and Anchor and Flags
Bit 0 of flags specifies 32 bit sprites.
Values that are $80 or $8080 are not updated.
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static void xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
static uint8_t gfx[256 + 128]; /* en-tête + une image 16x16, 4 bits par pixel */
static void images(uint8_t genre) { /* 1 : une tuile ; 2 : un sprite 16x16 */
gfx[0] = 1;
gfx[genre] = 1;
for (uint8_t y = 0; y < 16; y++)
for (uint8_t i = 0; i < 8; i++)
gfx[256 + y * 8 + i] = i < 4 ? 0x22 : 0x55; /* gauche : couleur 2, droite : 5 */
neo_file_store("img.gfx", gfx, sizeof gfx);
neo_file_load("img.gfx", (void *)0xFFFF); /* $FFFF : mémoire graphique */
}
static uint8_t sprite_pixel(uint16_t x, uint16_t y) { /* 5,36 : couche des sprites */
libre();
xy(0, x, y);
api(5, 36);
return ControlPort.params[0];
}
static void modifier(uint16_t x, uint16_t y, uint8_t image, uint8_t flip, uint8_t ancre) {
libre();
ControlPort.params[0] = 0; /* P0 : sprite 0 */
xy(1, x, y); /* P1-P4 : position */
ControlPort.params[5] = image;
ControlPort.params[6] = flip;
ControlPort.params[7] = ancre;
api(6, 2); /* Sprite Set */
}
/* Placer un sprite, puis ne changer que son retournement (groupe 6, fonction 2). */
int main(void) {
images(2);
modifier(200, 160, 0, 0, 7); /* image 0, ancre 7 : coin haut gauche */
uint8_t a = sprite_pixel(202, 165), b = sprite_pixel(212, 165);
modifier(0x8080, 0x8080, 0x80, 1, 0x80); /* seul le retournement change */
uint8_t c = sprite_pixel(202, 165), d = sprite_pixel(212, 165);
neo_sprite_reset();
printf("Image : %u %u, retournee : %u %u\n", a, b, c, d);
return 0;
}Image : 2 5, retournee : 5 2Mad Pascal
// Placer un sprite, puis ne changer que son retournement (groupe 6, fonction 2).
program placer;
uses crt, neo6502;
var a, b, c, d: byte;
gfx: array[0..383] of byte; // en-tête + une image 16x16
procedure images(genre: byte); // 1 : une tuile ; 2 : un sprite 16x16
var y, i: byte;
begin
fillchar(@gfx, 384, 0);
gfx[0] := 1;
gfx[genre] := 1;
for y := 0 to 15 do
for i := 0 to 7 do
if i < 4 then gfx[256 + y * 8 + i] := $22 // gauche : couleur 2
else gfx[256 + y * 8 + i] := $55; // droite : couleur 5
NeoSave('img.gfx', word(@gfx), 384);
NeoLoad('img.gfx', $FFFF); // $FFFF : mémoire graphique
end;
begin
images(2);
NeoUpdateSprite(0, 200, 160, 0, 0, 7); // Sprite Set : image 0, ancre 7 (coin haut gauche)
a := NeoGetSpritePixel(202, 165);
b := NeoGetSpritePixel(212, 165);
NeoUpdateSprite(0, $8080, $8080, $80, 1, $80); // seul le retournement change
c := NeoGetSpritePixel(202, 165);
d := NeoGetSpritePixel(212, 165);
NeoResetSprites;
writeln('Image : ', a, ' ', b, ', retournee : ', c, ' ', d);
end.Image : 2 5, retournee : 5 2NeoBASIC
10 ' Placer un sprite, puis ne changer que son retournement (groupe 6, fonction 2)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 2, 1 : ' en-tete
22 for y = 0 to 15 : for i = 0 to 7 : c = $22 : if i > 3 then c = $55
24 poke d + 256 + y * 8 + i, c : next i : next y : ' gauche : couleur 2, droite : 5
26 save "img.gfx", d, 384 : load "img.gfx", $ffff : ' $ffff : memoire graphique
30 sprite 0 image 0 anchor 7 to 200,160
40 a = spoint(202,165) : b = spoint(212,165)
50 sprite 0 flip 1
60 c = spoint(202,165) : d = spoint(212,165)
70 sprite clear
80 print "Image : ";a;" ";b;", retournee : ";c;" ";dImage : 2 5, retournee : 5 2Assembleur 65C02 (64tass)
; Placer un sprite, puis ne changer que son retournement (groupe 6, fonction 2).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr images ; un sprite 16x16
lda #200 ; ancre 7 : coin haut gauche en (200, 160)
ldy #160
jsr place
jsr lire2
stx a
sty b
jsr WaitMessage
stz ControlPort+4 ; P0 : sprite 0
lda #$80
ldx #6
_inch: sta ControlPort+5,x ; P1-P7 : $80, rien ne change...
dex
bpl _inch
lda #1
sta ControlPort+10 ; ... sauf P6 : retournement horizontal
lda #6
ldx #2 ; fonction 2 : Sprite Set
jsr appel
jsr lire2
stx c
sty d
jsr efface
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #<t4
ldx #>t4
jsr ecrire
lda c
jsr decimal
lda #<t6
ldx #>t6
jsr ecrire
lda d
jsr decimal
lda #13
jmp WriteCharacter
; Place le sprite 0 : X en A, Y en Y (inférieurs à 256), image 0, sans retournement, ancre dans ancre.
place: pha
jsr WaitMessage
pla
stz ControlPort+4 ; P0 : sprite 0
sta ControlPort+5 ; P1-P2 : X
stz ControlPort+6
sty ControlPort+7 ; P3-P4 : Y
stz ControlPort+8
stz ControlPort+9 ; P5 : image 0
stz ControlPort+10 ; P6 : pas de retournement
lda ancre
sta ControlPort+11 ; P7 : ancre
lda #6
ldx #2 ; 6,2 : Sprite Set
jmp appel
ancre: .byte 7
; Couleur de la couche des sprites en (A, Y), lue par 5,36, rendue dans A.
spixel: pha
jsr WaitMessage
pla
sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
lda #5
ldx #36 ; 5,36 : Read Sprite Pixel
jsr appel
lda ControlPort+4
rts
; Efface tous les sprites.
efface: jsr WaitMessage
lda #6
ldx #1 ; 6,1 : Sprite Reset
jmp appel
; Enregistre gfx dans img.gfx (3,3), puis le charge en mémoire graphique (3,2 vers $FFFF).
images: jsr WaitMessage
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #<gfx
sta ControlPort+6
lda #>gfx
sta ControlPort+7
lda #<384
sta ControlPort+8
lda #>384
sta ControlPort+9
lda #3
ldx #3 ; 3,3 : Save File
jsr appel
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #$FF
sta ControlPort+6 ; $FFFF : mémoire graphique
sta ControlPort+7
lda #3
ldx #2 ; 3,2 : Load File
jmp appel
nomgfx: .byte 7
.text "img.gfx"
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
gfx: .byte 1, 0, 1, 0 ; en-tête : un sprite 16x16
.fill 252
.rept 16 ; 16 lignes : gauche couleur 2, droite couleur 5
.byte $22, $22, $22, $22, $55, $55, $55, $55
.endrept
a: .byte 0
b: .byte 0
c: .byte 0
d: .byte 0
; Couche des sprites en (202, 165) dans X et en (212, 165) dans Y.
lire2: lda #202
ldy #165
jsr spixel
pha
lda #212
ldy #165
jsr spixel
tay
plx
rts
t0: .text "Image : ", 0
t2: .text " ", 0
t4: .text ", retournee : ", 0
t6: .text " ", 0Image : 2 5, retournee : 5 26,3 Sprite Hide Officiel
Cache un sprite sans oublier ses réglages.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du sprite |
Sorties : aucune.
Le sprite réapparaît au prochain 6,2 qui change sa position. Un sprite caché ne compte plus dans les collisions (6,4). En NeoBASIC, sprite n hide fait cet appel.
Mots-clés NeoBASIC qui font cet appel : sprite
Texte de la documentation du firmware (anglais)
Hide the sprite specified in Parameter:0.
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static void xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
static uint8_t gfx[256 + 128]; /* en-tête + une image 16x16, 4 bits par pixel */
static void images(uint8_t genre) { /* 1 : une tuile ; 2 : un sprite 16x16 */
gfx[0] = 1;
gfx[genre] = 1;
for (uint8_t y = 0; y < 16; y++)
for (uint8_t i = 0; i < 8; i++)
gfx[256 + y * 8 + i] = i < 4 ? 0x22 : 0x55; /* gauche : couleur 2, droite : 5 */
neo_file_store("img.gfx", gfx, sizeof gfx);
neo_file_load("img.gfx", (void *)0xFFFF); /* $FFFF : mémoire graphique */
}
static uint8_t sprite_pixel(uint16_t x, uint16_t y) { /* 5,36 : couche des sprites */
libre();
xy(0, x, y);
api(5, 36);
return ControlPort.params[0];
}
/* Cacher un sprite (groupe 6, fonction 3). */
int main(void) {
images(2);
neo_sprite_set(0, 200, 170, 0, 0, 0); /* 6,2 */
uint8_t a = sprite_pixel(200, 170);
neo_sprite_hide(0); /* Sprite Hide */
uint8_t b = sprite_pixel(200, 170);
neo_sprite_reset();
printf("Visible : %u, cache : %u\n", a, b);
return 0;
}Visible : 5, cache : 0Mad Pascal
// Cacher un sprite (groupe 6, fonction 3).
program cacher;
uses crt, neo6502;
var a, b: byte;
gfx: array[0..383] of byte; // en-tête + une image 16x16
procedure images(genre: byte); // 1 : une tuile ; 2 : un sprite 16x16
var y, i: byte;
begin
fillchar(@gfx, 384, 0);
gfx[0] := 1;
gfx[genre] := 1;
for y := 0 to 15 do
for i := 0 to 7 do
if i < 4 then gfx[256 + y * 8 + i] := $22 // gauche : couleur 2
else gfx[256 + y * 8 + i] := $55; // droite : couleur 5
NeoSave('img.gfx', word(@gfx), 384);
NeoLoad('img.gfx', $FFFF); // $FFFF : mémoire graphique
end;
begin
images(2);
NeoUpdateSprite(0, 200, 170, 0, 0, 0); // 6,2
a := NeoGetSpritePixel(200, 170);
NeoHideSprite(0); // Sprite Hide
b := NeoGetSpritePixel(200, 170);
NeoResetSprites;
writeln('Visible : ', a, ', cache : ', b);
end.Visible : 5, cache : 0NeoBASIC
10 ' Cacher un sprite (groupe 6, fonction 3)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 2, 1 : ' en-tete
22 for y = 0 to 15 : for i = 0 to 7 : c = $22 : if i > 3 then c = $55
24 poke d + 256 + y * 8 + i, c : next i : next y : ' gauche : couleur 2, droite : 5
26 save "img.gfx", d, 384 : load "img.gfx", $ffff : ' $ffff : memoire graphique
30 sprite 0 image 0 to 200,170
40 a = spoint(200,170)
50 sprite 0 hide
60 b = spoint(200,170)
70 sprite clear
80 print "Visible : ";a;", cache : ";bVisible : 5, cache : 0Assembleur 65C02 (64tass)
; Cacher un sprite (groupe 6, fonction 3).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr images ; un sprite 16x16
stz ancre ; ancre 0 : centre
lda #200
ldy #170
jsr place
lda #200
ldy #170
jsr spixel
sta a
jsr WaitMessage
stz ControlPort+4 ; P0 : sprite 0
lda #6
ldx #3 ; fonction 3 : Sprite Hide
jsr appel
lda #200
ldy #170
jsr spixel
sta b
jsr efface
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Place le sprite 0 : X en A, Y en Y (inférieurs à 256), image 0, sans retournement, ancre dans ancre.
place: pha
jsr WaitMessage
pla
stz ControlPort+4 ; P0 : sprite 0
sta ControlPort+5 ; P1-P2 : X
stz ControlPort+6
sty ControlPort+7 ; P3-P4 : Y
stz ControlPort+8
stz ControlPort+9 ; P5 : image 0
stz ControlPort+10 ; P6 : pas de retournement
lda ancre
sta ControlPort+11 ; P7 : ancre
lda #6
ldx #2 ; 6,2 : Sprite Set
jmp appel
ancre: .byte 7
; Couleur de la couche des sprites en (A, Y), lue par 5,36, rendue dans A.
spixel: pha
jsr WaitMessage
pla
sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
lda #5
ldx #36 ; 5,36 : Read Sprite Pixel
jsr appel
lda ControlPort+4
rts
; Efface tous les sprites.
efface: jsr WaitMessage
lda #6
ldx #1 ; 6,1 : Sprite Reset
jmp appel
; Enregistre gfx dans img.gfx (3,3), puis le charge en mémoire graphique (3,2 vers $FFFF).
images: jsr WaitMessage
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #<gfx
sta ControlPort+6
lda #>gfx
sta ControlPort+7
lda #<384
sta ControlPort+8
lda #>384
sta ControlPort+9
lda #3
ldx #3 ; 3,3 : Save File
jsr appel
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #$FF
sta ControlPort+6 ; $FFFF : mémoire graphique
sta ControlPort+7
lda #3
ldx #2 ; 3,2 : Load File
jmp appel
nomgfx: .byte 7
.text "img.gfx"
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
gfx: .byte 1, 0, 1, 0 ; en-tête : un sprite 16x16
.fill 252
.rept 16 ; 16 lignes : gauche couleur 2, droite couleur 5
.byte $22, $22, $22, $22, $55, $55, $55, $55
.endrept
a: .byte 0
b: .byte 0
t0: .text "Visible : ", 0
t2: .text ", cache : ", 0Visible : 5, cache : 06,4 Sprite Collision Officiel
Dit si les centres de deux sprites sont à une distance au plus égale à une valeur donnée.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | premier sprite |
P1 | uint8 | second sprite |
P2 | uint8 | distance maximale, en pixels |
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | non nul si la distance est inférieure ou égale |
erreur | uint8 | 1 si un numéro de sprite est invalide |
Le firmware compare le carré de la distance entre les points d'ancrage (les coordonnées données à 6,2) au carré de P2. Deux sprites doivent être visibles, sinon la réponse est 0. Les sprites de l'exemple sont à 20 pixels. En NeoBASIC, hit(a, b, d) fait cet appel.
Mots-clés NeoBASIC qui font cet appel : hit()
Texte de la documentation du firmware (anglais)
Parameter:0 is non-zero if the distance is less than or equal to Parameter:2 between the center of the sprite with index specified in Parameter:0 and the center of the sprite with index specified in Parameter:1 .
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static void xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
static uint8_t gfx[256 + 128]; /* en-tête + une image 16x16, 4 bits par pixel */
static void images(uint8_t genre) { /* 1 : une tuile ; 2 : un sprite 16x16 */
gfx[0] = 1;
gfx[genre] = 1;
for (uint8_t y = 0; y < 16; y++)
for (uint8_t i = 0; i < 8; i++)
gfx[256 + y * 8 + i] = i < 4 ? 0x22 : 0x55; /* gauche : couleur 2, droite : 5 */
neo_file_store("img.gfx", gfx, sizeof gfx);
neo_file_load("img.gfx", (void *)0xFFFF); /* $FFFF : mémoire graphique */
}
static uint8_t sprite_pixel(uint16_t x, uint16_t y) { /* 5,36 : couche des sprites */
libre();
xy(0, x, y);
api(5, 36);
return ControlPort.params[0];
}
/* Deux sprites à 20 pixels : se touchent-ils ? (groupe 6, fonction 4) */
int main(void) {
images(2);
neo_sprite_set(0, 100, 170, 0, 0, 0);
neo_sprite_set(1, 120, 170, 0, 0, 0);
uint8_t a = neo_sprite_collision(0, 1, 10); /* Sprite Collision */
uint8_t b = neo_sprite_collision(0, 1, 20);
neo_sprite_reset();
printf("Distance 10 : %u, distance 20 : %u\n", a, b);
return 0;
}Distance 10 : 0, distance 20 : 1Mad Pascal
// Deux sprites à 20 pixels : se touchent-ils ? (groupe 6, fonction 4)
program collision;
uses crt, neo6502;
var a, b: byte;
gfx: array[0..383] of byte; // en-tête + une image 16x16
procedure images(genre: byte); // 1 : une tuile ; 2 : un sprite 16x16
var y, i: byte;
begin
fillchar(@gfx, 384, 0);
gfx[0] := 1;
gfx[genre] := 1;
for y := 0 to 15 do
for i := 0 to 7 do
if i < 4 then gfx[256 + y * 8 + i] := $22 // gauche : couleur 2
else gfx[256 + y * 8 + i] := $55; // droite : couleur 5
NeoSave('img.gfx', word(@gfx), 384);
NeoLoad('img.gfx', $FFFF); // $FFFF : mémoire graphique
end;
begin
images(2);
NeoUpdateSprite(0, 100, 170, 0, 0, 0);
NeoUpdateSprite(1, 120, 170, 0, 0, 0);
a := NeoInRange(0, 1, 10); // Sprite Collision
b := NeoInRange(0, 1, 20);
NeoResetSprites;
writeln('Distance 10 : ', a, ', distance 20 : ', b);
end.Distance 10 : 0, distance 20 : 1NeoBASIC
10 ' Deux sprites a 20 pixels : se touchent-ils ? (groupe 6, fonction 4)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 2, 1 : ' en-tete
22 for y = 0 to 15 : for i = 0 to 7 : c = $22 : if i > 3 then c = $55
24 poke d + 256 + y * 8 + i, c : next i : next y : ' gauche : couleur 2, droite : 5
26 save "img.gfx", d, 384 : load "img.gfx", $ffff : ' $ffff : memoire graphique
30 sprite 0 image 0 to 100,170
40 sprite 1 image 0 to 120,170
50 a = hit(0,1,10) : b = hit(0,1,20)
60 sprite clear
70 print "Distance 10 : ";a;", distance 20 : ";bDistance 10 : 0, distance 20 : -1Assembleur 65C02 (64tass)
; Deux sprites à 20 pixels : se touchent-ils ? (groupe 6, fonction 4).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr images ; un sprite 16x16
stz ancre
lda #100
ldy #170
jsr place ; sprite 0 en (100, 170)
jsr WaitMessage
lda #1
sta ControlPort+4 ; sprite 1 en (120, 170) : mêmes réglages
lda #120
sta ControlPort+5
lda #6
ldx #2
jsr appel
lda #10
jsr touche
sta a
lda #20
jsr touche
sta b
jsr efface
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Place le sprite 0 : X en A, Y en Y (inférieurs à 256), image 0, sans retournement, ancre dans ancre.
place: pha
jsr WaitMessage
pla
stz ControlPort+4 ; P0 : sprite 0
sta ControlPort+5 ; P1-P2 : X
stz ControlPort+6
sty ControlPort+7 ; P3-P4 : Y
stz ControlPort+8
stz ControlPort+9 ; P5 : image 0
stz ControlPort+10 ; P6 : pas de retournement
lda ancre
sta ControlPort+11 ; P7 : ancre
lda #6
ldx #2 ; 6,2 : Sprite Set
jmp appel
ancre: .byte 7
; Couleur de la couche des sprites en (A, Y), lue par 5,36, rendue dans A.
spixel: pha
jsr WaitMessage
pla
sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
lda #5
ldx #36 ; 5,36 : Read Sprite Pixel
jsr appel
lda ControlPort+4
rts
; Efface tous les sprites.
efface: jsr WaitMessage
lda #6
ldx #1 ; 6,1 : Sprite Reset
jmp appel
; Enregistre gfx dans img.gfx (3,3), puis le charge en mémoire graphique (3,2 vers $FFFF).
images: jsr WaitMessage
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #<gfx
sta ControlPort+6
lda #>gfx
sta ControlPort+7
lda #<384
sta ControlPort+8
lda #>384
sta ControlPort+9
lda #3
ldx #3 ; 3,3 : Save File
jsr appel
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #$FF
sta ControlPort+6 ; $FFFF : mémoire graphique
sta ControlPort+7
lda #3
ldx #2 ; 3,2 : Load File
jmp appel
nomgfx: .byte 7
.text "img.gfx"
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
gfx: .byte 1, 0, 1, 0 ; en-tête : un sprite 16x16
.fill 252
.rept 16 ; 16 lignes : gauche couleur 2, droite couleur 5
.byte $22, $22, $22, $22, $55, $55, $55, $55
.endrept
a: .byte 0
b: .byte 0
; Sprites 0 et 1 à une distance d'au plus A ? Réponse dans A.
touche: pha
jsr WaitMessage
pla
sta ControlPort+6 ; P2 : distance
stz ControlPort+4 ; P0 : sprite 0
lda #1
sta ControlPort+5 ; P1 : sprite 1
lda #6
ldx #4 ; fonction 4 : Sprite Collision
jsr appel
lda ControlPort+4
rts
t0: .text "Distance 10 : ", 0
t2: .text ", distance 20 : ", 0Distance 10 : 0, distance 20 : 16,5 Sprite Position Officiel
Donne la position d'un sprite : les coordonnées de son point d'ancrage.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du sprite |
| Octets | Type | Rôle |
|---|---|---|
P1-P2 | uint16 | X |
P3-P4 | uint16 | Y |
erreur | uint8 | 1 si le numéro de sprite est invalide |
Ce sont les coordonnées données au dernier 6,2 (le point d'ancrage), pas le coin du sprite : l'exemple place le sprite avec l'ancre 7 et relit (150, 160). En NeoBASIC, spritex(n) et spritey(n) font cet appel.
Mots-clés NeoBASIC qui font cet appel : spritey()
Texte de la documentation du firmware (anglais)
Deposit into Parameters:1..4, the screen coordinates of the sprite with the index specified in Parameter:0.
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static void xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
static uint8_t gfx[256 + 128]; /* en-tête + une image 16x16, 4 bits par pixel */
static void images(uint8_t genre) { /* 1 : une tuile ; 2 : un sprite 16x16 */
gfx[0] = 1;
gfx[genre] = 1;
for (uint8_t y = 0; y < 16; y++)
for (uint8_t i = 0; i < 8; i++)
gfx[256 + y * 8 + i] = i < 4 ? 0x22 : 0x55; /* gauche : couleur 2, droite : 5 */
neo_file_store("img.gfx", gfx, sizeof gfx);
neo_file_load("img.gfx", (void *)0xFFFF); /* $FFFF : mémoire graphique */
}
static uint8_t sprite_pixel(uint16_t x, uint16_t y) { /* 5,36 : couche des sprites */
libre();
xy(0, x, y);
api(5, 36);
return ControlPort.params[0];
}
/* Relire la position d'un sprite (groupe 6, fonction 5). */
int main(void) {
uint16_t x, y;
images(2);
neo_sprite_set(0, 150, 160, 0, 0, 7); /* ancre 7 : coin haut gauche */
neo_sprite_position(0, &x, &y); /* Sprite Position */
neo_sprite_reset();
printf("Sprite 0 : %u, %u\n", x, y);
return 0;
}Sprite 0 : 150, 160Mad Pascal
// Relire la position d'un sprite (groupe 6, fonction 5).
program position;
uses crt, neo6502;
var x, y: word;
gfx: array[0..383] of byte; // en-tête + une image 16x16
procedure images(genre: byte); // 1 : une tuile ; 2 : un sprite 16x16
var y, i: byte;
begin
fillchar(@gfx, 384, 0);
gfx[0] := 1;
gfx[genre] := 1;
for y := 0 to 15 do
for i := 0 to 7 do
if i < 4 then gfx[256 + y * 8 + i] := $22 // gauche : couleur 2
else gfx[256 + y * 8 + i] := $55; // droite : couleur 5
NeoSave('img.gfx', word(@gfx), 384);
NeoLoad('img.gfx', $FFFF); // $FFFF : mémoire graphique
end;
begin
images(2);
NeoUpdateSprite(0, 150, 160, 0, 0, 7); // ancre 7 : coin haut gauche
NeoGetSpriteXY(0, x, y); // Sprite Position
NeoResetSprites;
writeln('Sprite 0 : ', x, ', ', y);
end.Sprite 0 : 150, 160NeoBASIC
10 ' Relire la position d'un sprite (groupe 6, fonction 5)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 2, 1 : ' en-tete
22 for y = 0 to 15 : for i = 0 to 7 : c = $22 : if i > 3 then c = $55
24 poke d + 256 + y * 8 + i, c : next i : next y : ' gauche : couleur 2, droite : 5
26 save "img.gfx", d, 384 : load "img.gfx", $ffff : ' $ffff : memoire graphique
30 sprite 0 image 0 anchor 7 to 150,160
40 x = spritex(0) : y = spritey(0)
50 sprite clear
60 print "Sprite 0 : ";x;", ";ySprite 0 : 150, 160Assembleur 65C02 (64tass)
; Relire la position d'un sprite (groupe 6, fonction 5).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr images ; un sprite 16x16
lda #150 ; ancre 7 : coin haut gauche
ldy #160
jsr place
jsr WaitMessage
stz ControlPort+4 ; P0 : sprite 0
lda #6
ldx #5 ; fonction 5 : Sprite Position
jsr appel
lda ControlPort+5 ; P1 : X (poids faible, < 256 ici)
sta x
lda ControlPort+7 ; P3 : Y
sta y
jsr efface
lda #<t0
ldx #>t0
jsr ecrire
lda x
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda y
jsr decimal
lda #13
jmp WriteCharacter
; Place le sprite 0 : X en A, Y en Y (inférieurs à 256), image 0, sans retournement, ancre dans ancre.
place: pha
jsr WaitMessage
pla
stz ControlPort+4 ; P0 : sprite 0
sta ControlPort+5 ; P1-P2 : X
stz ControlPort+6
sty ControlPort+7 ; P3-P4 : Y
stz ControlPort+8
stz ControlPort+9 ; P5 : image 0
stz ControlPort+10 ; P6 : pas de retournement
lda ancre
sta ControlPort+11 ; P7 : ancre
lda #6
ldx #2 ; 6,2 : Sprite Set
jmp appel
ancre: .byte 7
; Couleur de la couche des sprites en (A, Y), lue par 5,36, rendue dans A.
spixel: pha
jsr WaitMessage
pla
sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
lda #5
ldx #36 ; 5,36 : Read Sprite Pixel
jsr appel
lda ControlPort+4
rts
; Efface tous les sprites.
efface: jsr WaitMessage
lda #6
ldx #1 ; 6,1 : Sprite Reset
jmp appel
; Enregistre gfx dans img.gfx (3,3), puis le charge en mémoire graphique (3,2 vers $FFFF).
images: jsr WaitMessage
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #<gfx
sta ControlPort+6
lda #>gfx
sta ControlPort+7
lda #<384
sta ControlPort+8
lda #>384
sta ControlPort+9
lda #3
ldx #3 ; 3,3 : Save File
jsr appel
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #$FF
sta ControlPort+6 ; $FFFF : mémoire graphique
sta ControlPort+7
lda #3
ldx #2 ; 3,2 : Load File
jmp appel
nomgfx: .byte 7
.text "img.gfx"
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
gfx: .byte 1, 0, 1, 0 ; en-tête : un sprite 16x16
.fill 252
.rept 16 ; 16 lignes : gauche couleur 2, droite couleur 5
.byte $22, $22, $22, $22, $55, $55, $55, $55
.endrept
x: .byte 0
y: .byte 0
t0: .text "Sprite 0 : ", 0
t2: .text ", ", 0Sprite 0 : 150, 160