Tachibana
Language: English

Group 6 — Sprites Official

6,1 Sprite Reset · 6,2 Sprite Set · 6,3 Sprite Hide · 6,4 Sprite Collision · 6,5 Sprite Position

A sprite is an image from graphics memory (see group 5) shown over the screen without damaging it: sprites use the high 4 bits of each pixel, the background the low 4 bits. 5,36 reads the sprite layer, 5,33 the background.

6,2 places a sprite. Its image number is the index of the image (0 to 63) among the 16 × 16 sprites, or among the 32 × 32 sprites when $40 is added. The value $80 means "unchanged", as do $8080 for the position and $80 for flip and anchor: a single setting can thus be changed. NeoBASIC clears bit 7 of the image number, so sprite n image $80 (the 5,7 numbering) means image 0 there; through the direct call, $80 on a new sprite draws nothing (checked on the bench).

The anchor tells which point of the sprite lies at the given coordinates: 0 the centre, then 1 to 9 like the numeric keypad (7 top left, 5 centre, 3 bottom right). The firmware documentation mentions a flags byte (32 bits) in P8; the code does not read it, the size comes from bit 6 of the image number.

The examples load the group 5 graphics file declared as one 16 × 16 sprite (left half colour 2, right half colour 5), and clear the sprites (6,1) before returning.

6,1 Sprite Reset Official

Removes all sprites and resets the sprite system.

Inputs: none.

Outputs: none.

In NeoBASIC, sprite clear makes this call, as does clear (and so run).

NeoBASIC keywords that make this call: clear, sprite

Firmware documentation text

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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Avant : 5, apres : 0
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Avant : 5, apres : 0
NeoBASIC
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 : ";b
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Avant : 5, apres : 0
65C02 assembly (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 : ", 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Avant : 5, apres : 0

6,2 Sprite Set Official

Places or updates a sprite: position, image, flip, anchor.

Inputs
BytesTypeMeaning
P0uint8sprite number
P1-P2uint16X ($8080: unchanged)
P3-P4uint16Y
P5uint8image: 0-63 16×16 sprites, +$40 32×32 sprites; $80: unchanged
P6uint8flip: bit 0 horizontal, bit 1 vertical; $80: unchanged
P7uint8anchor 0 to 9; $80: unchanged
Outputs
BytesTypeMeaning
erreuruint81 invalid sprite number or anchor, 2 missing image

The example places the sprite with anchor 7 (its top left corner at (200, 160)), then only changes the flip: position $8080, image $80 and anchor $80 are left as they are, and the two halves swap. In NeoBASIC, sprite n image i anchor a flip f to x,y makes this call.

NeoBASIC keywords that make this call: sprite

Firmware documentation text

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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Image : 2 5, retournee : 5 2
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Image : 2 5, retournee : 5 2
NeoBASIC
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;" ";d
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Image : 2 5, retournee : 5 2
65C02 assembly (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 " ", 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Image : 2 5, retournee : 5 2

6,3 Sprite Hide Official

Hides a sprite while keeping its settings.

Inputs
BytesTypeMeaning
P0uint8sprite number

Outputs: none.

The sprite comes back at the next 6,2 that changes its position. A hidden sprite no longer counts in collisions (6,4). In NeoBASIC, sprite n hide makes this call.

NeoBASIC keywords that make this call: sprite

Firmware documentation text

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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Visible : 5, cache : 0
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Visible : 5, cache : 0
NeoBASIC
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 : ";b
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Visible : 5, cache : 0
65C02 assembly (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 : ", 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Visible : 5, cache : 0

6,4 Sprite Collision Official

Tells whether the centres of two sprites are at most a given distance apart.

Inputs
BytesTypeMeaning
P0uint8first sprite
P1uint8second sprite
P2uint8maximum distance, in pixels
Outputs
BytesTypeMeaning
P0uint8non zero if the distance is less than or equal
erreuruint81 if a sprite number is invalid

The firmware compares the square of the distance between the anchor points (the coordinates given to 6,2) with the square of P2. Both sprites must be visible, otherwise the answer is 0. The example sprites are 20 pixels apart. In NeoBASIC, hit(a, b, d) makes this call.

NeoBASIC keywords that make this call: hit()

Firmware documentation text

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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Distance 10 : 0, distance 20 : 1
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Distance 10 : 0, distance 20 : 1
NeoBASIC
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 : ";b
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Distance 10 : 0, distance 20 : -1
65C02 assembly (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 : ", 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Distance 10 : 0, distance 20 : 1

6,5 Sprite Position Official

Gives the position of a sprite: the coordinates of its anchor point.

Inputs
BytesTypeMeaning
P0uint8sprite number
Outputs
BytesTypeMeaning
P1-P2uint16X
P3-P4uint16Y
erreuruint81 if the sprite number is invalid

These are the coordinates given to the last 6,2 (the anchor point), not the sprite corner: the example places the sprite with anchor 7 and reads (150, 160) back. In NeoBASIC, spritex(n) and spritey(n) make this call.

NeoBASIC keywords that make this call: spritey()

Firmware documentation text

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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Sprite 0 : 150, 160
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Sprite 0 : 150, 160
NeoBASIC
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;", ";y
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Sprite 0 : 150, 160
65C02 assembly (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 ", ", 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Sprite 0 : 150, 160

← The Neo6502 API