Tachibana
Langue : français

Groupe 5 — Graphisme Officiel

5,1 Set Defaults · 5,2 Draw Line · 5,3 Draw Rectangle · 5,4 Draw Ellipse · 5,5 Draw Pixel · 5,6 Draw Text · 5,7 Draw Image · 5,8 Draw Tilemap · 5,9 Set Graphics Mode · 5,10 Get Graphics Mode · 5,11 Set Draw Page · 5,12 Set Display Page · 5,32 Set Palette · 5,33 Read Pixel · 5,34 Reset Palette · 5,35 Set Tilemap · 5,36 Read Sprite Pixel · 5,37 Frame Count · 5,38 Get Palette · 5,39 Write Pixel · 5,40 Get Late Scanlines · 5,41 Get Bus Stalls · 5,42 Get Bus Timing · 5,64 Set Color · 5,65 Set Solid Flag · 5,66 Set Draw Size · 5,67 Set Flip Bits

Le groupe 5 dessine dans la mémoire graphique : 320 × 240 pixels en mode 0, un octet par pixel qui désigne une couleur de la palette. Les coordonnées sont des entiers signés de 16 bits (P0-P1 et P2-P3 pour le premier point, P4-P5 et P6-P7 pour le second) ; ce qui sort de l'écran est ignoré.

La couleur d'un tracé suit la règle du firmware : nouveau pixel = (ancien pixel ET masque) OU EXCLUSIF couleur. 5,1 règle le masque et la couleur ensemble ; 5,64 met le masque à 0, et le pixel prend alors simplement la couleur donnée.

Les images (5,7), les cartes de tuiles (5,8) et les sprites (groupe 6) se lisent dans une mémoire graphique séparée, remplie en chargeant un fichier à l'adresse $FFFF (3,2). Ce fichier commence par un en-tête de 256 octets : octet 0 non nul, puis les nombres de tuiles 16 × 16, de sprites 16 × 16 et de sprites 32 × 32 ; suivent les images, 4 bits par pixel, pixel de gauche dans le quartet haut, la couleur 0 étant transparente. Les exemples fabriquent un tel fichier de 384 octets : une image 16 × 16, moitié gauche couleur 2, moitié droite couleur 5.

Pour vérifier ce qui est dessiné sans capture d'écran, chaque exemple relit des pixels avec 5,33 et affiche leur couleur. Les dessins sont faits dans le bas de l'écran, là où la console n'a encore rien écrit.

5,1 Set Defaults Officiel

Règle d'un coup le masque et la couleur du tracé, le remplissage, la taille (images et texte) et le retournement.

Entrées
OctetsTypeRôle
P0uint8masque (ET) appliqué à l'ancien pixel
P1uint8couleur (OU EXCLUSIF)
P2uint8remplissage : non nul pour des formes pleines (et un fond plein pour texte et images)
P3uint8taille des images et du texte
P4uint8retournement : bit 0 horizontal, bit 1 vertical

Sorties : aucune.

Nouveau pixel = (ancien ET masque) OU EXCLUSIF couleur. Avec le masque $FF, la couleur s'ajoute par OU EXCLUSIF : tracer deux fois le même point le rend à sa couleur d'origine, ce que montre l'exemple. En NeoBASIC, ink m, c (ou ink c, masque 0), solid, frame et dim font cet appel.

Texte de la documentation du firmware (anglais)

Configure the global graphics system settings. Not all parameters are relevant for all graphics commands; but all parameters will be set by this command. So mind their values. Refer to Section "Graphics Settings" for details.

The parameters are And, Or, Fill Flag, Extent, and Flip. Bit 0 of flip sets the horizontal flip, Bit 1 sets the vertical flip.

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Tracer deux fois le même point en OU EXCLUSIF (groupe 5, fonction 1). */
int main(void) {
    neo_graphics_set_defaults(0xFF, 3, 0, 1, 0);   /* Set Defaults : masque $FF, couleur 3 */
    neo_graphics_draw_pixel(200, 170);          /* 5,5 */
    uint8_t a = neo_graphics_read_pixel(200, 170);
    neo_graphics_draw_pixel(200, 170);          /* même point : 3 XOR 3 = 0 */
    uint8_t b = neo_graphics_read_pixel(200, 170);
    printf("Premier trace : %u, second trace : %u\n", a, b);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Premier trace : 3, second trace : 0
Mad Pascal
// Tracer deux fois le même point en OU EXCLUSIF (groupe 5, fonction 1).
program defauts;
uses crt, neo6502;
var a, b: byte;
begin
  NeoSetDefaults($FF, 3, 0, 1, 0);              // Set Defaults : masque $FF, couleur 3
  NeoDrawPixel(200, 170);                       // 5,5
  a := NeoGetPixel(200, 170);
  NeoDrawPixel(200, 170);                       // même point : 3 XOR 3 = 0
  b := NeoGetPixel(200, 170);
  writeln('Premier trace : ', a, ', second trace : ', b);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Premier trace : 3, second trace : 0
NeoBASIC
10 ' Tracer deux fois le meme point en OU EXCLUSIF (groupe 5, fonction 1)
20 plot 0,0 ink $ff,3 to 200,170 : a = point(200,170) : ' ink masque, couleur : 5,1
30 plot to 200,170 : b = point(200,170)
40 print "Premier trace : ";a;", second trace : ";b
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Premier trace : 3, second trace : 0
Assembleur 65C02 (64tass)
; Tracer deux fois le même point en OU EXCLUSIF (groupe 5, 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 WaitMessage
        lda #$FF
        sta ControlPort+4          ; P0 : masque $FF
        lda #3
        sta ControlPort+5          ; P1 : couleur 3
        stz ControlPort+6          ; P2 : pas de remplissage
        lda #1
        sta ControlPort+7          ; P3 : taille 1
        stz ControlPort+8          ; P4 : pas de retournement
        ldx #1                     ; fonction 1 : Set Defaults
        jsr g5
        jsr trace
        sta a
        jsr trace                  ; même point : 3 XOR 3 = 0
        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

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        jmp appel

; Trace le point (200, 170) par 5,5 et relit sa couleur.
trace:  lda #200
        ldy #170
        jsr point1
        ldx #5                     ; 5,5 : Draw Pixel
        jsr g5
        lda #200
        ldy #170
        jmp lire

; 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

a:      .byte 0
b:      .byte 0
t0:     .text "Premier trace : ", 0
t2:     .text ", second trace : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Premier trace : 3, second trace : 0

5,2 Draw Line Officiel

Trace un segment entre deux points.

Entrées
OctetsTypeRôle
P0-P1int16X du premier point
P2-P3int16Y du premier point
P4-P5int16X du second point
P6-P7int16Y du second point

Sorties : aucune.

En NeoBASIC, line x1,y1 to x2,y2 fait cet appel (avec ink pour la couleur).

Texte de la documentation du firmware (anglais)

Draw a line between the screen coordinates specified in Parameters:0,1,Parameters:2,3 (begin X,Y) and Parameters:4,5,Parameters:6,7 (end X,Y).

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Tracer une ligne horizontale (groupe 5, fonction 2). */
int main(void) {
    neo_graphics_set_color(3);                  /* 5,64 */
    neo_graphics_draw_line(150, 200, 250, 200); /* Draw Line */
    uint8_t a = neo_graphics_read_pixel(200, 200);
    uint8_t b = neo_graphics_read_pixel(200, 201);
    printf("Sur la ligne : %u, juste dessous : %u\n", a, b);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Sur la ligne : 3, juste dessous : 0
Mad Pascal
// Tracer une ligne horizontale (groupe 5, fonction 2).
program ligne;
uses crt, neo6502;
var a, b: byte;
begin
  NeoSetColor(3);                               // 5,64
  NeoDrawLine(150, 200, 250, 200);              // Draw Line
  a := NeoGetPixel(200, 200);
  b := NeoGetPixel(200, 201);
  writeln('Sur la ligne : ', a, ', juste dessous : ', b);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Sur la ligne : 3, juste dessous : 0
NeoBASIC
10 ' Tracer une ligne horizontale (groupe 5, fonction 2)
20 line 150,200 ink 3 to 250,200
30 a = point(200,200) : b = point(200,201)
40 print "Sur la ligne : ";a;", juste dessous : ";b
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Sur la ligne : 3, juste dessous : 0
Assembleur 65C02 (64tass)
; Tracer une ligne horizontale (groupe 5, 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 WaitMessage
        lda #3
        sta ControlPort+4          ; P0 : couleur 3
        ldx #64                    ; 5,64 : Set Color
        jsr g5
        lda #150
        ldy #200
        jsr point1                 ; P0-P3 : (150, 200)
        lda #250
        ldy #200
        jsr point2                 ; P4-P7 : (250, 200)
        ldx #2                     ; fonction 2 : Draw Line
        jsr g5
        lda #200
        ldy #200
        jsr lire
        sta a
        lda #200
        ldy #201
        jsr lire
        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

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        jmp appel

; 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

a:      .byte 0
b:      .byte 0
t0:     .text "Sur la ligne : ", 0
t2:     .text ", juste dessous : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Sur la ligne : 3, juste dessous : 0

5,3 Draw Rectangle Officiel

Trace un rectangle défini par deux coins opposés, plein ou en contour selon le drapeau de remplissage.

Entrées
OctetsTypeRôle
P0-P1int16X du premier point
P2-P3int16Y du premier point
P4-P5int16X du second point
P6-P7int16Y du second point

Sorties : aucune.

Contour ou plein selon 5,65 (ou 5,1). En NeoBASIC, rect x1,y1 to x2,y2 fait cet appel ; frame et solid choisissent le contour ou le plein.

Texte de la documentation du firmware (anglais)

Draw a rectangle spanning the screen coordinates specified in Parameters:0,1,Parameters:2,3 (corner X,Y) and Parameters:4,5,Parameters:6,7 (opposite corner X,Y).

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Tracer le contour d'un rectangle (groupe 5, fonction 3). */
int main(void) {
    neo_graphics_set_color(4);                  /* 5,64 */
    neo_graphics_set_solid_flag(0);             /* 5,65 : contour */
    neo_graphics_draw_rectangle(150, 160, 190, 200);
    uint8_t a = neo_graphics_read_pixel(150, 180);
    uint8_t b = neo_graphics_read_pixel(170, 180);
    printf("Bord : %u, centre : %u\n", a, b);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Bord : 4, centre : 0
Mad Pascal
// Tracer le contour d'un rectangle (groupe 5, fonction 3).
program forme3;
uses crt, neo6502;
var a, b: byte;
begin
  NeoSetColor(4);                               // 5,64
  NeoSetSolidFlag(0);                            // 5,65 : contour
  NeoDrawRect(150, 160, 190, 200);
  a := NeoGetPixel(150, 180);
  b := NeoGetPixel(170, 180);
  writeln('Bord : ', a, ', centre : ', b);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Bord : 4, centre : 0
NeoBASIC
10 ' Tracer le contour d'un rectangle (groupe 5, fonction 3)
20 rect 150,160 ink 4 frame to 190,200
30 a = point(150,180) : b = point(170,180)
40 print "Bord : ";a;", centre : ";b
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Bord : 4, centre : 0
Assembleur 65C02 (64tass)
; Tracer le contour d'un rectangle (groupe 5, 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 WaitMessage
        lda #4
        sta ControlPort+4          ; P0 : couleur 4
        ldx #64                    ; 5,64 : Set Color
        jsr g5
        lda #0
        sta ControlPort+4          ; P0 : contour
        ldx #65                    ; 5,65 : Set Solid Flag
        jsr g5
        lda #150
        ldy #160
        jsr point1
        lda #190
        ldy #200
        jsr point2
        ldx #3                     ; 5,3
        jsr g5
        lda #150
        ldy #180
        jsr lire
        sta a
        lda #170
        ldy #180
        jsr lire
        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

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        jmp appel

; 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

a:      .byte 0
b:      .byte 0
t0:     .text "Bord : ", 0
t2:     .text ", centre : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Bord : 4, centre : 0

5,4 Draw Ellipse Officiel

Trace l'ellipse inscrite dans le rectangle défini par deux coins opposés.

Entrées
OctetsTypeRôle
P0-P1int16X du premier point
P2-P3int16Y du premier point
P4-P5int16X du second point
P6-P7int16Y du second point

Sorties : aucune.

Pleine ou en contour selon le drapeau de remplissage (5,65). Un carré donne un cercle. En NeoBASIC, ellipse x1,y1 to x2,y2 fait cet appel.

Texte de la documentation du firmware (anglais)

Draw an ellipse spanning the screen coordinates specified in Parameters:0,1,Parameters:2,3 (corner X,Y) and Parameters:4,5,Parameters:6,7 (opposite corner X,Y).

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Tracer une ellipse pleine (groupe 5, fonction 4). */
int main(void) {
    neo_graphics_set_color(4);                  /* 5,64 */
    neo_graphics_set_solid_flag(1);             /* 5,65 : plein */
    neo_graphics_draw_ellipse(200, 160, 240, 200);
    uint8_t a = neo_graphics_read_pixel(220, 180);
    uint8_t b = neo_graphics_read_pixel(201, 161);
    printf("Centre : %u, coin : %u\n", a, b);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Centre : 4, coin : 0
Mad Pascal
// Tracer une ellipse pleine (groupe 5, fonction 4).
program forme4;
uses crt, neo6502;
var a, b: byte;
begin
  NeoSetColor(4);                               // 5,64
  NeoSetSolidFlag(1);                            // 5,65 : plein
  NeoDrawEllipse(200, 160, 240, 200);
  a := NeoGetPixel(220, 180);
  b := NeoGetPixel(201, 161);
  writeln('Centre : ', a, ', coin : ', b);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Centre : 4, coin : 0
NeoBASIC
10 ' Tracer une ellipse pleine (groupe 5, fonction 4)
20 ellipse 200,160 ink 4 solid to 240,200
30 a = point(220,180) : b = point(201,161)
40 print "Centre : ";a;", coin : ";b
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Centre : 4, coin : 0
Assembleur 65C02 (64tass)
; Tracer une ellipse pleine (groupe 5, 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 WaitMessage
        lda #4
        sta ControlPort+4          ; P0 : couleur 4
        ldx #64                    ; 5,64 : Set Color
        jsr g5
        lda #1
        sta ControlPort+4          ; P0 : plein
        ldx #65                    ; 5,65 : Set Solid Flag
        jsr g5
        lda #200
        ldy #160
        jsr point1
        lda #240
        ldy #200
        jsr point2
        ldx #4                     ; 5,4
        jsr g5
        lda #220
        ldy #180
        jsr lire
        sta a
        lda #201
        ldy #161
        jsr lire
        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

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        jmp appel

; 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

a:      .byte 0
b:      .byte 0
t0:     .text "Centre : ", 0
t2:     .text ", coin : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Centre : 4, coin : 0

5,5 Draw Pixel Officiel

Trace un pixel dans la couleur courante.

Entrées
OctetsTypeRôle
P0-P1int16X du point
P2-P3int16Y du point

Sorties : aucune.

Le pixel suit la règle masque/couleur de 5,1 ; 5,39 écrit au contraire une couleur telle quelle. En NeoBASIC, plot to x,y fait cet appel (plot x,y seul ne fait que déplacer le point courant).

Texte de la documentation du firmware (anglais)

Draw a single pixel at the screen coordinates specified in Parameters:0,1,Parameters:2,3 (X,Y).

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Allumer un pixel (groupe 5, fonction 5). */
int main(void) {
    neo_graphics_set_color(6);                  /* 5,64 */
    neo_graphics_draw_pixel(210, 170);          /* 5,5 : Draw Pixel */
    uint8_t a = neo_graphics_read_pixel(210, 170);   /* 5,33 */
    uint8_t b = neo_graphics_read_pixel(211, 170);
    printf("Pixel (210, 170) : %u, voisin : %u\n", a, b);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel (210, 170) : 6, voisin : 0
Mad Pascal
// Allumer un pixel (groupe 5, fonction 5).
program pixel5;
uses crt, neo6502;
var a, b: byte;
begin
  NeoSetColor(6);                               // 5,64
  NeoDrawPixel(210, 170);                       // 5,5 : Draw Pixel
  a := NeoGetPixel(210, 170);                   // 5,33
  b := NeoGetPixel(211, 170);
  writeln('Pixel (210, 170) : ', a, ', voisin : ', b);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel (210, 170) : 6, voisin : 0
NeoBASIC
10 ' Allumer un pixel (groupe 5, fonction 5)
20 plot 0,0 ink 6 to 210,170
30 a = point(210,170) : b = point(211,170)
40 print "Pixel (210, 170) : ";a;", voisin : ";b
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel (210, 170) : 6, voisin : 0
Assembleur 65C02 (64tass)
; Allumer un pixel (groupe 5, 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 WaitMessage
        lda #6
        sta ControlPort+4          ; P0 : couleur 6
        ldx #64                    ; 5,64 : Set Color
        jsr g5
        lda #210
        ldy #170
        jsr point1
        ldx #5                     ; 5,5 : Draw Pixel
        jsr g5
        lda #210
        ldy #170
        jsr lire                   ; 5,33 : Read Pixel
        sta a
        lda #211
        ldy #170
        jsr lire
        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

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        jmp appel

; 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

a:      .byte 0
b:      .byte 0
t0:     .text "Pixel (210, 170) : ", 0
t2:     .text ", voisin : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel (210, 170) : 6, voisin : 0

5,6 Draw Text Officiel

Écrit un texte en mode graphique, à une position en pixels.

Entrées
OctetsTypeRôle
P0-P1int16X du coin haut gauche, en pixels
P2-P3int16Y du coin haut gauche, en pixels
P4-P5addradresse du texte (précédé de sa longueur)

Sorties : aucune.

La documentation du firmware parle d'une case de caractère ; le code (GFXScaledText) prend des coordonnées en pixels, ce que confirme l'exemple. Taille (5,66), couleur et fond plein (5,65) s'appliquent. L'exemple compte les pixels allumés dans un carré de 14 pixels autour de la lettre A. En NeoBASIC, text "…" to x,y fait cet appel.

Texte de la documentation du firmware (anglais)

Draw the length-prefixed string of text stored at the memory location specified in Parameters:4,5 at the screen character cell specified in Parameters:0,1,Parameters:2,3 (X,Y).

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

static uint16_t compte(uint8_t couleur, uint8_t x0, uint8_t y0, uint8_t cote) {   /* pixels de cette couleur */
    uint16_t n = 0;
    for (uint8_t y = y0; y < y0 + cote; y++)
        for (uint8_t x = x0; x < x0 + cote; x++)
            if (neo_graphics_read_pixel(x, y) == couleur)
                n++;
    return n;
}

/* Écrire A en mode graphique et compter ses pixels (groupe 5, fonction 6). */
int main(void) {
    neo_graphics_set_color(5);
    neo_graphics_draw_text(200, 170, "A");      /* Draw Text */
    printf("Pixels du A en couleur 5 : %u\n", compte(5, 198, 168, 14));
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixels du A en couleur 5 : 16
Mad Pascal
// Écrire A en mode graphique et compter ses pixels (groupe 5, fonction 6).
program texte;
uses crt, neo6502;
var s: string[4];

function compte(couleur, x0, y0, cote: byte): word;   // pixels de cette couleur
var x, y: byte;
begin
  result := 0;
  for y := y0 to y0 + cote - 1 do
    for x := x0 to x0 + cote - 1 do
      if NeoGetPixel(x, y) = couleur then inc(result);
end;

begin
  NeoSetColor(5);
  s := 'A';
  NeoDrawString(200, 170, s);                   // Draw Text
  writeln('Pixels du A en couleur 5 : ', compte(5, 198, 168, 14));
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixels du A en couleur 5 : 16
NeoBASIC
10 ' Ecrire A en mode graphique et compter ses pixels (groupe 5, fonction 6)
20 text "A" dim 1 ink 5 to 200,170
30 n = 0 : for y = 168 to 181 : for x = 198 to 211
40 if point(x,y) = 5 then n = n + 1
50 next x : next y
60 print "Pixels du A en couleur 5 : ";n
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixels du A en couleur 5 : 16
Assembleur 65C02 (64tass)
; Écrire A en mode graphique et compter ses pixels (groupe 5, fonction 6).
        .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 WaitMessage
        lda #5
        sta ControlPort+4
        ldx #64                    ; 5,64 : couleur 5
        jsr g5
        lda #200
        ldy #170
        jsr point1                 ; P0-P3 : (200, 170)
        lda #<lettre
        sta ControlPort+8          ; P4-P5 : texte
        lda #>lettre
        sta ControlPort+9
        ldx #6                     ; fonction 6 : Draw Text
        jsr g5
        jsr compte
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda n
        jsr decimal
        lda #13
        jmp WriteCharacter

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        jmp appel

; Compte les pixels de couleur coul dans le carré (x0, y0), côté cote ; résultat dans n.
compte: stz n
        lda y0
        sta yc
_ly:    lda x0
        sta xc
_lx:    lda xc
        ldy yc
        jsr lire
        cmp coul
        bne _pas
        inc n
_pas:   inc xc
        lda xc
        sec
        sbc x0
        cmp cote
        bne _lx
        inc yc
        lda yc
        sec
        sbc y0
        cmp cote
        bne _ly
        rts
xc:     .byte 0
yc:     .byte 0
n:      .byte 0

; 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

lettre: .byte 1
        .text "A"
coul:   .byte 5
x0:     .byte 198
y0:     .byte 168
cote:   .byte 14
t0:     .text "Pixels du A en couleur 5 : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixels du A en couleur 5 : 16

5,7 Draw Image Officiel

Dessine une image de la mémoire graphique (tuile ou sprite) à une position donnée.

Entrées
OctetsTypeRôle
P0-P1int16X du coin haut gauche
P2-P3int16Y du coin haut gauche
P4uint8numéro d'image : $00-$7F tuiles 16×16, $80-$BF sprites 16×16, $C0-$FF sprites 32×32

Sorties : aucune.

La taille (5,66), le retournement (5,67) et le fond plein (5,65) s'appliquent ; la couleur 0 de l'image est transparente sauf en fond plein. Sans mémoire graphique chargée, rien n'est dessiné. En NeoBASIC, image n to x,y fait cet appel (image n, retournement dim taille to x,y).

Texte de la documentation du firmware (anglais)

Draw the image with image ID in Parameter:4 at the screen coordinates Parameters:0,1,Parameters:2,3 (X,Y). The extent and flip settings influence this command.

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

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 */
}

/* Dessiner une image de la mémoire graphique (groupe 5, fonction 7). */
int main(void) {
    images(1);
    neo_graphics_set_draw_size(1);             /* 5,66 */
    neo_graphics_set_flip_bits(0);             /* 5,67 */
    neo_graphics_draw_image(200, 160, 0);         /* 5,7 : Draw Image, image 0 */
    uint8_t a = neo_graphics_read_pixel(202, 165);
    neo_graphics_set_draw_size(1);             /* 5,66 */
    neo_graphics_set_flip_bits(0);             /* 5,67 */
    neo_graphics_draw_image(200, 160, 0);         /* 5,7 : Draw Image, image 0 */
    uint8_t b = neo_graphics_read_pixel(212, 165);
    printf("Gauche : %u, droite : %u\n", a, b);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Gauche : 2, droite : 5
Mad Pascal
// Dessiner une image de la mémoire graphique (groupe 5, fonction 7).
program image7;
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(1);
  NeoSetDrawSize(1);                            // 5,66
  NeoSetFlip(0);                                // 5,67
  NeoDrawImage(200, 160, 0);                      // 5,7 : Draw Image, image 0
  a := NeoGetPixel(202, 165);
  NeoSetDrawSize(1);                            // 5,66
  NeoSetFlip(0);                                // 5,67
  NeoDrawImage(200, 160, 0);                      // 5,7 : Draw Image, image 0
  b := NeoGetPixel(212, 165);
  writeln('Gauche : ', a, ', ', 'droite : ', b);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Gauche : 2, droite : 5
NeoBASIC
10 ' Dessiner une image de la memoire graphique (groupe 5, fonction 7)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 1, 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 image 0 to 200,160 : a = point(202,165)
40 image 0 to 200,160 : b = point(212,165)
50 print "Gauche : ";a; ", ";"droite : ";b
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Gauche : 2, droite : 5
Assembleur 65C02 (64tass)
; Dessiner une image de la mémoire graphique (groupe 5, fonction 7).
        .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 WaitMessage
        jsr images
        lda #1
        sta ControlPort+4
        ldx #66                    ; 5,66 : taille 1
        jsr g5
        lda #0
        sta ControlPort+4
        ldx #67                    ; 5,67 : retournement 0
        jsr g5
        lda #200
        ldy #160
        jsr point1
        stz ControlPort+8          ; P4 : image 0
        ldx #7                     ; 5,7 : Draw Image
        jsr g5
        lda #202
        ldy #165
        jsr lire
        sta a
        lda #1
        sta ControlPort+4
        ldx #66                    ; 5,66 : taille 1
        jsr g5
        lda #0
        sta ControlPort+4
        ldx #67                    ; 5,67 : retournement 0
        jsr g5
        lda #200
        ldy #160
        jsr point1
        stz ControlPort+8          ; P4 : image 0
        ldx #7                     ; 5,7 : Draw Image
        jsr g5
        lda #212
        ldy #165
        jsr lire
        sta b
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda a
        jsr decimal
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda #<t3
        ldx #>t3
        jsr ecrire
        lda b
        jsr decimal
        lda #13
        jmp WriteCharacter

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        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, 1, 0, 0             ; en-tête : une tuile
        .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 "Gauche : ", 0
t2:     .text ", ", 0
t3:     .text "droite : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Gauche : 2, droite : 5

5,8 Draw Tilemap Modifié par Trinity

Dessine la carte de tuiles courante (5,35) dans un rectangle de l'écran.

Entrées
OctetsTypeRôle
P0-P1int16X du premier point
P2-P3int16Y du premier point
P4-P5int16X du second point
P6-P7int16Y du second point
Sorties
OctetsTypeRôle
erreuruint81 sans carte, si le décalage sort de la carte ou si la fenêtre est moins large qu'une tuile

Tuiles 16×16 (32×32 en taille 2, voir 5,66), lues dans la mémoire graphique. La carte a deux tuiles 0 côte à côte : on lit donc 2 (gauche de la première), 5 (sa droite), puis 2 (gauche de la seconde). La fenêtre fait |x2-x1| pixels de large et |y2-y1| de haut : les bords droit et bas sont exclus. La carte commence par 3 octets (type, largeur, hauteur en tuiles), puis un octet par tuile ($F0 transparente, $F1-$FF couleur unie). Avec le type $81 au lieu de 1 (Trinity), un pixel de couleur 0 laisse l'écran tel quel, de même que la partie de la fenêtre hors de la carte : on superpose ainsi des cartes (plans de parallaxe). Trinity dessine aussi les cartes dans les modes 1 et 2. En NeoBASIC, tiledraw x1,y1 to x2,y2 fait cet appel.

Texte de la documentation du firmware (anglais)

Draw the current tilemap at the screen coordinates specified in Parameters:0,1,Parameters:2,3 (top-left X,Y) and Parameters:4,5,Parameters:6,7 (bottom-right X,Y) using current graphics settings. The window is |x2-x1| pixels wide and |y2-y1| high : the right and bottom edges are excluded. The tilemap starts with 3 bytes : type, width, height (in tiles), then one byte per tile ($F0 transparent, $F1-$FF solid colour). Type bit 7 set ($81 rather than 1, Trinity T-92) : a pixel of colour 0 in a tile leaves the screen as it is, and so does the part of the window beyond the map, so that maps can be drawn over each other (parallax layers).

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

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 const uint8_t carte[] = { 1, 2, 1, 0, 0 };   /* format, largeur 2, hauteur 1, tuiles 0 0 */

/* Dessiner une carte de deux tuiles (groupe 5, fonction 8). */
int main(void) {
    images(1);
    neo_graphics_set_tilemap(carte, 0, 0);      /* 5,35 */
    neo_graphics_draw_tilemap(150, 160, 182, 176);   /* 5,8 : Draw Tilemap */
    uint8_t a = neo_graphics_read_pixel(152, 165);
    uint8_t b = neo_graphics_read_pixel(160, 165);
    uint8_t c = neo_graphics_read_pixel(168, 165);
    printf("Couleurs sur la ligne : %u %u %u\n", a, b, c);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleurs sur la ligne : 2 5 2
Mad Pascal
// Dessiner une carte de deux tuiles (groupe 5, fonction 8).
program carte8;
uses crt, neo6502;
var a, b, c: byte;
    carte: array[0..4] of byte = (1, 2, 1, 0, 0);   // format, largeur 2, hauteur 1, tuiles 0 0
    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(1);
  NeoSelectTileMap(word(@carte), 0, 0);         // 5,35
  NeoDrawTileMap(150, 160, 182, 176);           // 5,8 : Draw Tilemap
  a := NeoGetPixel(152, 165);
  b := NeoGetPixel(160, 165);
  c := NeoGetPixel(168, 165);
  writeln('Couleurs sur la ligne : ', a, ' ', b, ' ', c);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleurs sur la ligne : 2 5 2
NeoBASIC
10 ' Dessiner une carte de deux tuiles (groupe 5, fonction 8)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 1, 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 m = alloc(8) : poke m, 1 : poke m + 1, 2 : poke m + 2, 1 : poke m + 3, 0 : poke m + 4, 0 : ' carte 2 x 1
40 tilemap m, 0, 0
50 tiledraw 150,160 to 182,176
60 a = point(152,165) : b = point(160,165) : c = point(168,165)
70 print "Couleurs sur la ligne : ";a;" ";b;" ";c
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleurs sur la ligne : 2 5 2
Assembleur 65C02 (64tass)
; Dessiner une carte de deux tuiles (groupe 5, fonction 8).
        .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 WaitMessage
        jsr images
        jsr WaitMessage
        lda #<carte
        sta ControlPort+4          ; P0-P1 : carte
        lda #>carte
        sta ControlPort+5
        stz ControlPort+6          ; P2-P5 : décalage (0, 0)
        stz ControlPort+7
        stz ControlPort+8
        stz ControlPort+9
        ldx #35                    ; 5,35 : Set Tilemap
        jsr g5
        lda #150
        ldy #160
        jsr point1
        lda #182
        ldy #176
        jsr point2
        ldx #8                     ; 5,8 : Draw Tilemap
        jsr g5
        lda #152
        ldy #165
        jsr lire
        sta a
        lda #160
        ldy #165
        jsr lire
        sta b
        lda #168
        ldy #165
        jsr lire
        sta c
        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 #13
        jmp WriteCharacter

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        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, 1, 0, 0             ; en-tête : une tuile
        .fill 252
        .rept 16                   ; 16 lignes : gauche couleur 2, droite couleur 5
        .byte $22, $22, $22, $22, $55, $55, $55, $55
        .endrept
carte:  .byte 1, 2, 1, 0, 0         ; format, largeur 2, hauteur 1, tuiles 0 0
a:      .byte 0
b:      .byte 0
c:      .byte 0
t0:     .text "Couleurs sur la ligne : ", 0
t2:     .text " ", 0
t4:     .text " ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleurs sur la ligne : 2 5 2

5,9 Set Graphics Mode Trinity

Choisit le mode d'affichage et réinitialise écran, palette et console.

Entrées
OctetsTypeRôle
P0uint8mode : 0 standard 320×240 en 256 couleurs, 1 Hercules 720×350 monochrome, 2 essai 320×240 en 16 couleurs
Sorties
OctetsTypeRôle
erreuruint8non nul si le mode est inconnu ou non pris en charge par le matériel

Propre à Trinity. Le mode 2 est un essai (Trinity 0.16.58), qui peut changer ou disparaître : 320×240 en 16 couleurs, deux pixels par octet (celui de gauche dans les 4 bits hauts), deux pages (5,11, 5,12), couleurs 0 à 15, console de 53×30 ; pas de couche de sprites (ils sont dessinés en XOR, comme en mode 1). L'ancien mode 2 du fork, en 320×256, a été retiré. Les sprites et les images n'existent qu'en mode 0 ; les cartes de tuiles se dessinent aussi dans les modes 1 et 2. L'exemple passe en mode 2, relit ses dimensions (5,10), puis revient au mode 0 ; l'écran étant effacé à chaque changement, il garde ses résultats et les affiche à la fin.

Texte de la documentation du firmware (anglais)

Select the display mode in Parameter:0 and reinitialise the screen, palette and console (F5 / ADR-02). 0 is the standard 320x240 256 colour mode. 1 is the Hercules mode (720x350 monochrome, 80x25 text in 9x14 cells). 2 is a TRIAL mode (Trinity T-90, study) : 320x240 in 16 colours, 4 bits per pixel, two pixels per byte, left pixel in the high nibble, two pages (5,11 / 5,12), palette entries 0-15, same display timing as mode 0 ; no sprite layer (sprites are drawn in XOR as in mode 1), console 53x30. It may change or go. (The fork's 320x256x16 mode 2 was removed on 2026-09-19.) Tilemaps are drawn in modes 1 and 2 too (packed path of 5,8). Sets the error flag if the mode is unknown or not supported by this hardware.

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 mode, bpp, cols, lignes;
static uint16_t largeur, hauteur;

static void lire_mode(void) {                   /* 5,10 : Get Graphics Mode */
    libre();
    api(5, 10);
    mode = ControlPort.params[0];
    largeur = ControlPort.params[1] | (ControlPort.params[2] << 8);
    hauteur = ControlPort.params[3] | (ControlPort.params[4] << 8);
    bpp = ControlPort.params[5];
    cols = ControlPort.params[6];
    lignes = ControlPort.params[7];
}

static uint8_t choisir(uint8_t m) {             /* Set Graphics Mode, erreur rendue */
    libre();
    ControlPort.params[0] = m;
    api(5, 9);
    return ControlPort.error;
}

/* Changer de mode d'affichage (groupe 5, fonction 9, Trinity). */
int main(void) {
    uint8_t e2 = choisir(2);                    /* essai 320x240, 16 couleurs */
    lire_mode();                                /* 5,10 */
    uint16_t l2 = largeur, h2 = hauteur;
    uint8_t e0 = choisir(0);                    /* retour au mode standard (écran effacé) */
    lire_mode();
    printf("Mode 2 : erreur %u, %u x %u\n", e2, l2, h2);
    printf("Mode 0 : erreur %u, %u x %u\n", e0, largeur, hauteur);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Mode 2 : erreur 0, 320 x 240
Mode 0 : erreur 0, 320 x 240
Mad Pascal
// Changer de mode d'affichage (groupe 5, fonction 9, Trinity).
program choisirmode;
uses crt, neo6502;
var e2, e0: byte;
    largeur, hauteur, l2, h2: word;

function choisir(m: byte): byte;                // Set Graphics Mode, erreur rendue
begin
  NeoWaitMessage;
  NeoMessage.params[0] := m;
  NeoSendMessage(5, 9);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

procedure lire_mode;                            // 5,10 : Get Graphics Mode
begin
  NeoSendMessage(5, 10);
  NeoWaitMessage;
  largeur := wordxParams[0];
  hauteur := wordxParams[1];
end;

begin
  e2 := choisir(2);                             // essai 320x240, 16 couleurs
  lire_mode;
  l2 := largeur;
  h2 := hauteur;
  e0 := choisir(0);                             // retour au mode standard (écran effacé)
  lire_mode;
  writeln('Mode 2 : erreur ', e2, ', ', l2, ' x ', h2);
  writeln('Mode 0 : erreur ', e0, ', ', largeur, ' x ', hauteur);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Mode 2 : erreur 0, 320 x 240
Mode 0 : erreur 0, 320 x 240
NeoBASIC
10 ' Changer de mode d'affichage (groupe 5, fonction 9, Trinity)
20 m = 2 : gosub 1000 : e2 = e : l2 = l : h2 = h : ' essai 320x240, 16 couleurs
30 m = 0 : gosub 1000 : ' retour au mode standard (ecran efface)
40 print "Mode 2 : erreur ";e2;", ";l2;" x ";h2
50 print "Mode 0 : erreur ";e;", ";l;" x ";h
60 end
1000 ' 5,9 : mode m, erreur dans e ; puis 5,10 : largeur l, hauteur h
1010 while peek($ff00) : wend : poke $ff04, m : poke $ff01, 9 : poke $ff00, 5
1020 while peek($ff00) : wend : e = peek($ff02)
1030 poke $ff01, 10 : poke $ff00, 5
1040 while peek($ff00) : wend : l = deek($ff05) : h = deek($ff07)
1050 return
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Mode 2 : erreur 0, 320 x 240
Mode 0 : erreur 0, 320 x 240
Assembleur 65C02 (64tass)
; Changer de mode d'affichage (groupe 5, fonction 9, Trinity).
        .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:  lda #2                     ; essai 320x240, 16 couleurs
        jsr choisir
        sta e2
        ldy #0
        jsr taille                 ; dimensions du mode 2 en dim
        lda #0                     ; retour au mode standard (écran effacé)
        jsr choisir
        sta e0
        ldy #4
        jsr taille                 ; dimensions du mode 0 en dim+4
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda e2
        jsr decimal
        ldy #0
        jsr montrer
        lda #<t1
        ldx #>t1
        jsr ecrire
        lda e0
        jsr decimal
        ldy #4
        jmp montrer

; 5,10 : largeur et hauteur (P1-P4) copiées en dim+Y, à l'abri avant d'afficher.
taille: jsr WaitMessage
        lda #5
        ldx #10                    ; 5,10 : Get Graphics Mode
        jsr appel
        ldx #0
_copie: lda ControlPort+5,x
        sta dim,y
        iny
        inx
        cpx #4
        bne _copie
        rts

; Affiche « , largeur x hauteur » des dimensions en dim+Y, puis un retour à la ligne.
montrer:
        sty ou
        lda #<t2
        ldx #>t2
        jsr ecrire
        ldy ou
        lda dim,y                  ; largeur
        ldx dim+1,y
        jsr decimal16
        lda #<t3
        ldx #>t3
        jsr ecrire
        ldy ou
        lda dim+2,y                ; hauteur
        ldx dim+3,y
        jsr decimal16
        lda #13
        jmp WriteCharacter
ou:     .byte 0

; Mode A (5,9), erreur rendue dans A.
choisir:
        pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0 : mode
        lda #5
        ldx #9                     ; fonction 9 : Set Graphics Mode
        jsr appel
        lda ControlPort+2
        rts

; Affiche en décimal le nombre de 16 bits A (poids faible) X (poids fort), jusqu'à 999.
decimal16:
        stx fort
        ldy #0                     ; centaines
_c:     sec
        sbc #100
        pha
        lda fort
        sbc #0
        bcc _cf
        sta fort
        pla
        iny
        bra _c
_cf:    pla
        clc
        adc #100
        pha
        tya
        beq _d
        ora #'0'
        jsr WriteCharacter
        pla
        jmp decimal2
_d:     pla
        jmp decimal
decimal2:                          ; A (0-99) sur deux chiffres
        ldy #0
_dz:    cmp #10
        bcc _u
        sbc #10
        iny
        bra _dz
_u:     pha
        tya
        ora #'0'
        jsr WriteCharacter
        pla
        ora #'0'
        jmp WriteCharacter
fort:   .byte 0

; 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

e2:     .byte 0
e0:     .byte 0
dim:    .fill 8
t0:     .text "Mode 2 : erreur ", 0
t1:     .text "Mode 0 : erreur ", 0
t2:     .text ", ", 0
t3:     .text " x ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Mode 2 : erreur 0, 320 x 240
Mode 0 : erreur 0, 320 x 240

5,10 Get Graphics Mode Trinity

Donne le mode d'affichage courant et ses dimensions.

Entrées : aucune.

Sorties
OctetsTypeRôle
P0uint8mode
P1-P2uint16largeur en pixels
P3-P4uint16hauteur en pixels
P5uint8bits par pixel
P6-P7uint8console : colonnes, puis lignes

Propre à Trinity. En mode 0 : 320 × 240, 8 bits par pixel, console de 53 colonnes sur 30 lignes (police 6 × 8).

Texte de la documentation du firmware (anglais)

Return the current display mode in Parameter:0, the pixel width in Parameters:1,2, the pixel height in Parameters:3,4, the bits per pixel in Parameter:5 and the console size in characters in Parameters:6,7.

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 mode, bpp, cols, lignes;
static uint16_t largeur, hauteur;

static void lire_mode(void) {                   /* 5,10 : Get Graphics Mode */
    libre();
    api(5, 10);
    mode = ControlPort.params[0];
    largeur = ControlPort.params[1] | (ControlPort.params[2] << 8);
    hauteur = ControlPort.params[3] | (ControlPort.params[4] << 8);
    bpp = ControlPort.params[5];
    cols = ControlPort.params[6];
    lignes = ControlPort.params[7];
}

/* Lire le mode d'affichage (groupe 5, fonction 10, Trinity). */
int main(void) {
    lire_mode();
    printf("Mode %u : %u x %u, %u bits, console %u x %u\n", mode, largeur, hauteur, bpp, cols, lignes);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Mode 0 : 320 x 240, 8 bits, console 53 x 30
Mad Pascal
// Lire le mode d'affichage (groupe 5, fonction 10, Trinity).
program litmode;
uses crt, neo6502;
var mode, bpp, cols, lignes: byte;
    largeur, hauteur: word;
begin
  NeoWaitMessage;
  NeoSendMessage(5, 10);                        // Get Graphics Mode
  NeoWaitMessage;
  mode := NeoMessage.params[0];
  largeur := wordxParams[0];                    // P1-P2
  hauteur := wordxParams[1];                    // P3-P4
  bpp := NeoMessage.params[5];
  cols := NeoMessage.params[6];
  lignes := NeoMessage.params[7];
  writeln('Mode ', mode, ' : ', largeur, ' x ', hauteur, ', ', bpp, ' bits, console ', cols, ' x ', lignes);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Mode 0 : 320 x 240, 8 bits, console 53 x 30
NeoBASIC
10 ' Lire le mode d'affichage (groupe 5, fonction 10, Trinity)
20 while peek($ff00) : wend : poke $ff01, 10 : poke $ff00, 5
30 while peek($ff00) : wend : m = peek($ff04) : l = peek($ff05) + 256 * peek($ff06) : h = peek($ff07) + 256 * peek($ff08)
40 b = peek($ff09) : c = peek($ff0a) : r = peek($ff0b)
50 print "Mode ";m;" : ";l;" x ";h;", ";b;" bits, console ";c;" x ";r
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Mode 0 : 320 x 240, 8 bits, console 53 x 30
Assembleur 65C02 (64tass)
; Lire le mode d'affichage (groupe 5, fonction 10, Trinity).
        .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 WaitMessage
        lda #5
        ldx #10                    ; fonction 10 : Get Graphics Mode
        jsr appel
        ldx #7
_copie: lda ControlPort+4,x        ; P0-P7 à l'abri avant d'afficher
        sta p,x
        dex
        bpl _copie
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda p
        jsr decimal
        lda #<t1
        ldx #>t1
        jsr ecrire
        lda p+1                    ; 320 = $0140 : poids fort 1
        ldx p+2
        jsr decimal16
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda p+3
        ldx p+4
        jsr decimal16
        lda #<t3
        ldx #>t3
        jsr ecrire
        lda p+5
        jsr decimal
        lda #<t4
        ldx #>t4
        jsr ecrire
        lda p+6
        jsr decimal
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda p+7
        jsr decimal
        lda #13
        jmp WriteCharacter

; Affiche en décimal le nombre de 16 bits A (poids faible) X (poids fort), jusqu'à 999.
decimal16:
        stx fort
        ldy #0                     ; centaines
_c:     sec
        sbc #100
        pha
        lda fort
        sbc #0
        bcc _cf
        sta fort
        pla
        iny
        bra _c
_cf:    pla
        clc
        adc #100
        pha
        tya
        beq _d
        ora #'0'
        jsr WriteCharacter
        pla
        jmp decimal2
_d:     pla
        jmp decimal
decimal2:                          ; A (0-99) sur deux chiffres
        ldy #0
_dz:    cmp #10
        bcc _u
        sbc #10
        iny
        bra _dz
_u:     pha
        tya
        ora #'0'
        jsr WriteCharacter
        pla
        ora #'0'
        jmp WriteCharacter
fort:   .byte 0

; 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

p:      .fill 8
t0:     .text "Mode ", 0
t1:     .text " : ", 0
t2:     .text " x ", 0
t3:     .text ", ", 0
t4:     .text " bits, console ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Mode 0 : 320 x 240, 8 bits, console 53 x 30

5,11 Set Draw Page Trinity

Choisit la page dans laquelle dessinent la console et les fonctions graphiques.

Entrées
OctetsTypeRôle
P0uint8page : 0, ou 1 dans les modes 1 et 2
Sorties
OctetsTypeRôle
erreuruint8non nul si la page n'existe pas dans le mode courant

Propre à Trinity. Le mode 0 n'a qu'une page, les modes 1 et 2 (l'essai en 16 couleurs, voir 5,9) en ont deux : on dessine dans l'une pendant que l'autre est affichée (5,12). Selon la documentation de Trinity 0.16.69 (non essayé au banc), la page n commence en mémoire vidéo à n × (octets par ligne × lignes), adresse que le blitter atteint par les pages $80 et $81 : en mode 2, la page 1 est en $80:9600 (160 × 240) ; en mode 1, en $80:7B0C (90 × 350). L'exemple, en mode 0, montre le refus de la page 1.

Texte de la documentation du firmware (anglais)

Select the page (Parameter:0) that console and graphics commands draw into (F-55). Mode 0 has one page, modes 1 and 2 have two (0 and 1) ; mode 2 is the 16 colour trial of T-90. Sets the error flag if the page does not exist. Page n starts at offset n x (bytes per line x lines) of the video RAM, which is what the blitter addresses as pages $80/$81 : in mode 2, page 1 is at $80:9600 (38400 = 160 x 240), so a 12,3 into the hidden page targets $80:9600 + y x 160 + x / 2, with target format 5 (even x) or 6 (odd x). In mode 1, page 1 is at $80:7B0C (31500 = 90 x 350).

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 page(uint8_t p) {                /* Set Draw Page, erreur rendue */
    libre();
    ControlPort.params[0] = p;
    api(5, 11);
    return ControlPort.error;
}

/* Choisir la page où l'on dessine (groupe 5, fonction 11, Trinity). */
int main(void) {
    uint8_t e1 = page(1);                       /* le mode 0 n'a qu'une page */
    uint8_t e0 = page(0);
    printf("Page 1 : erreur %u, page 0 : erreur %u\n", e1, e0);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Page 1 : erreur 1, page 0 : erreur 0
Mad Pascal
// Choisir la page où l'on dessine (groupe 5, fonction 11, Trinity).
program page11;
uses crt, neo6502;
var e1, e0: byte;

function page(p: byte): byte;                   // Set Draw Page, erreur rendue
begin
  NeoWaitMessage;
  NeoMessage.params[0] := p;
  NeoSendMessage(5, 11);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

begin
  e1 := page(1);                                // le mode 0 n'a qu'une page
  e0 := page(0);
  writeln('Page 1 : erreur ', e1, ', page 0 : erreur ', e0);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Page 1 : erreur 1, page 0 : erreur 0
NeoBASIC
10 ' Choisir la page où l'on dessine (groupe 5, fonction 11, Trinity)
20 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 11 : poke $ff00, 5
30 while peek($ff00) : wend : e1 = peek($ff02)
40 poke $ff04, 0 : poke $ff01, 11 : poke $ff00, 5
50 while peek($ff00) : wend : e0 = peek($ff02)
60 print "Page 1 : erreur ";e1;", page 0 : erreur ";e0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Page 1 : erreur 1, page 0 : erreur 0
Assembleur 65C02 (64tass)
; Choisir la page où l'on dessine (groupe 5, fonction 11, Trinity).
        .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:  lda #1                     ; le mode 0 n'a qu'une page
        jsr page
        sta e1
        lda #0
        jsr page
        sta e0
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda e1
        jsr decimal
        lda #<t1
        ldx #>t1
        jsr ecrire
        lda e0
        jsr decimal
        lda #13
        jmp WriteCharacter

; Page A (5,11), erreur rendue dans A.
page:   pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0 : page
        lda #5
        ldx #11                    ; fonction 11 : Set Draw Page
        jsr appel
        lda ControlPort+2
        rts

; 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

e1:     .byte 0
e0:     .byte 0
t0:     .text "Page 1 : erreur ", 0
t1:     .text ", page 0 : erreur ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Page 1 : erreur 1, page 0 : erreur 0

5,12 Set Display Page Trinity

Choisit la page affichée à partir de la trame suivante.

Entrées
OctetsTypeRôle
P0uint8page : 0, ou 1 dans les modes 1 et 2
Sorties
OctetsTypeRôle
erreuruint8non nul si la page n'existe pas dans le mode courant

Propre à Trinity. Le changement a lieu à la trame suivante : attendre que 5,37 change pour être sûr qu'il est fait. L'exemple, en mode 0 (une seule page), montre le refus de la page 1.

Texte de la documentation du firmware (anglais)

Select the page (Parameter:0) shown on screen from the next frame (F-55). Use Function 37 (Frame Count) to wait for the swap. Sets the error flag if the page does not exist.

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 page(uint8_t p) {                /* Set Display Page, erreur rendue */
    libre();
    ControlPort.params[0] = p;
    api(5, 12);
    return ControlPort.error;
}

/* Choisir la page affichée (groupe 5, fonction 12, Trinity). */
int main(void) {
    uint8_t e1 = page(1);                       /* le mode 0 n'a qu'une page */
    uint8_t e0 = page(0);
    printf("Page 1 : erreur %u, page 0 : erreur %u\n", e1, e0);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Page 1 : erreur 1, page 0 : erreur 0
Mad Pascal
// Choisir la page affichée (groupe 5, fonction 12, Trinity).
program page12;
uses crt, neo6502;
var e1, e0: byte;

function page(p: byte): byte;                   // Set Display Page, erreur rendue
begin
  NeoWaitMessage;
  NeoMessage.params[0] := p;
  NeoSendMessage(5, 12);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

begin
  e1 := page(1);                                // le mode 0 n'a qu'une page
  e0 := page(0);
  writeln('Page 1 : erreur ', e1, ', page 0 : erreur ', e0);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Page 1 : erreur 1, page 0 : erreur 0
NeoBASIC
10 ' Choisir la page affichee (groupe 5, fonction 12, Trinity)
20 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 12 : poke $ff00, 5
30 while peek($ff00) : wend : e1 = peek($ff02)
40 poke $ff04, 0 : poke $ff01, 12 : poke $ff00, 5
50 while peek($ff00) : wend : e0 = peek($ff02)
60 print "Page 1 : erreur ";e1;", page 0 : erreur ";e0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Page 1 : erreur 1, page 0 : erreur 0
Assembleur 65C02 (64tass)
; Choisir la page affichée (groupe 5, fonction 12, Trinity).
        .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:  lda #1                     ; le mode 0 n'a qu'une page
        jsr page
        sta e1
        lda #0
        jsr page
        sta e0
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda e1
        jsr decimal
        lda #<t1
        ldx #>t1
        jsr ecrire
        lda e0
        jsr decimal
        lda #13
        jmp WriteCharacter

; Page A (5,12), erreur rendue dans A.
page:   pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0 : page
        lda #5
        ldx #12                    ; fonction 12 : Set Display Page
        jsr appel
        lda ControlPort+2
        rts

; 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

e1:     .byte 0
e0:     .byte 0
t0:     .text "Page 1 : erreur ", 0
t1:     .text ", page 0 : erreur ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Page 1 : erreur 1, page 0 : erreur 0

5,32 Set Palette Officiel

Change la couleur d'un numéro de la palette.

Entrées
OctetsTypeRôle
P0uint8numéro de couleur
P1uint8rouge (0-255)
P2uint8vert (0-255)
P3uint8bleu (0-255)

Sorties : aucune.

Tout ce qui est déjà affiché dans cette couleur change aussitôt. 5,34 rend la palette d'origine. En NeoBASIC, palette n, r, g, b fait cet appel.

Mots-clés NeoBASIC qui font cet appel : palette

Texte de la documentation du firmware (anglais)

Set the palette colour at the index spcified in Parameter:0 to the values in Parameter:1,Parameter:2,Parameter:3 (RGB).

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;
}

/* Changer puis relire une couleur de la palette (groupe 5, fonction 32). */
int main(void) {
    neo_graphics_set_palette(5, 255, 128, 0);   /* Set Palette : orange */
    libre();
    ControlPort.params[0] = 5;
    api(5, 38);                                 /* 5,38 : Get Palette */
    printf("Couleur 5 : %u %u %u\n", ControlPort.params[1], ControlPort.params[2], ControlPort.params[3]);
    neo_graphics_reset_palette();               /* 5,34 */
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleur 5 : 255 128 0
Mad Pascal
// Changer puis relire une couleur de la palette (groupe 5, fonction 32).
program palette;
uses crt, neo6502;
var r, g, b: byte;
begin
  NeoSetPalette(5, 255, 128, 0);                // Set Palette : orange
  NeoGetPalette(5, r, g, b);                    // 5,38
  NeoResetPalette;                              // 5,34
  writeln('Couleur 5 : ', r, ' ', g, ' ', b);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleur 5 : 255 128 0
NeoBASIC
10 ' Changer puis relire une couleur de la palette (groupe 5, fonction 32)
20 palette 5, 255, 128, 0
30 while peek($ff00) : wend : poke $ff04, 5 : poke $ff01, 38 : poke $ff00, 5 : ' 5,38
40 while peek($ff00) : wend : r = peek($ff05) : g = peek($ff06) : b = peek($ff07)
50 print "Couleur 5 : ";r;" ";g;" ";b
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleur 5 : 255 128 0
Assembleur 65C02 (64tass)
; Changer puis relire une couleur de la palette (groupe 5, fonction 32).
        .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 WaitMessage
        lda #5
        sta ControlPort+4          ; P0 : couleur 5
        lda #255
        sta ControlPort+5          ; P1-P3 : rouge, vert, bleu
        lda #128
        sta ControlPort+6
        stz ControlPort+7
        ldx #32                    ; fonction 32 : Set Palette
        jsr g5
        lda #5
        sta ControlPort+4
        ldx #38                    ; 5,38 : Get Palette
        jsr g5
        lda ControlPort+5
        sta r
        lda ControlPort+6
        sta v
        lda ControlPort+7
        sta b
        ldx #34                    ; 5,34 : Reset Palette
        jsr g5
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda r
        jsr decimal
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda v
        jsr decimal
        lda #<t4
        ldx #>t4
        jsr ecrire
        lda b
        jsr decimal
        lda #13
        jmp WriteCharacter

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        jmp appel

; 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

r:      .byte 0
v:      .byte 0
b:      .byte 0
t0:     .text "Couleur 5 : ", 0
t2:     .text " ", 0
t4:     .text " ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleur 5 : 255 128 0

5,33 Read Pixel Officiel

Lit la couleur d'un pixel de l'écran.

Entrées
OctetsTypeRôle
P0-P1int16X du point
P2-P3int16Y du point
Sorties
OctetsTypeRôle
P0uint8couleur : 0 à 255, ou 0 à 15 (fond seul) quand des sprites sont affichés
erreuruint81 si le point est hors de l'écran

Quand des sprites sont utilisés, le firmware ne rend que les 4 bits bas (le fond) ; 5,36 lit la couche des sprites. En NeoBASIC, point(x, y) fait cet appel.

Mots-clés NeoBASIC qui font cet appel : point()

Texte de la documentation du firmware (anglais)

Read a single pixel at the screen coordinates specified in Parameters:0,1,Parameters:2,3 (X,Y). When the routine completes, the result will be in Parameter:0. If sprites are in use, this will be the background only (0..15), if sprites are not in use it may return (0..255)

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Lire la couleur d'un pixel (groupe 5, fonction 33). */
int main(void) {
    neo_graphics_set_color(6);                  /* 5,64 */
    neo_graphics_draw_pixel(210, 170);          /* 5,5 */
    uint8_t a = neo_graphics_read_pixel(210, 170);   /* 5,33 : Read Pixel */
    uint8_t b = neo_graphics_read_pixel(211, 170);
    printf("Pixel (210, 170) : %u, voisin : %u\n", a, b);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel (210, 170) : 6, voisin : 0
Mad Pascal
// Lire la couleur d'un pixel (groupe 5, fonction 33).
program pixel33;
uses crt, neo6502;
var a, b: byte;
begin
  NeoSetColor(6);                               // 5,64
  NeoDrawPixel(210, 170);                       // 5,5
  a := NeoGetPixel(210, 170);                   // 5,33 : Read Pixel
  b := NeoGetPixel(211, 170);
  writeln('Pixel (210, 170) : ', a, ', voisin : ', b);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel (210, 170) : 6, voisin : 0
NeoBASIC
10 ' Lire la couleur d'un pixel (groupe 5, fonction 33)
20 plot 0,0 ink 6 to 210,170
30 a = point(210,170) : b = point(211,170)
40 print "Pixel (210, 170) : ";a;", voisin : ";b
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel (210, 170) : 6, voisin : 0
Assembleur 65C02 (64tass)
; Lire la couleur d'un pixel (groupe 5, fonction 33).
        .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 WaitMessage
        lda #6
        sta ControlPort+4          ; P0 : couleur 6
        ldx #64                    ; 5,64 : Set Color
        jsr g5
        lda #210
        ldy #170
        jsr point1
        ldx #5                     ; 5,5 : Draw Pixel
        jsr g5
        lda #210
        ldy #170
        jsr lire                   ; 5,33 : Read Pixel
        sta a
        lda #211
        ldy #170
        jsr lire
        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

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        jmp appel

; 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

a:      .byte 0
b:      .byte 0
t0:     .text "Pixel (210, 170) : ", 0
t2:     .text ", voisin : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel (210, 170) : 6, voisin : 0

5,34 Reset Palette Officiel

Rend à la palette ses couleurs d'origine.

Entrées : aucune.

Sorties : aucune.

L'exemple change la couleur 1 en (1, 2, 3), remet la palette d'origine et relit la couleur 1. En NeoBASIC, palette clear fait cet appel.

Mots-clés NeoBASIC qui font cet appel : palette

Texte de la documentation du firmware (anglais)

Reset the palette to the defaults.

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;
}

/* Changer une couleur, puis remettre la palette d'origine (groupe 5, fonction 34). */
int main(void) {
    neo_graphics_set_palette(1, 1, 2, 3);       /* 5,32 */
    neo_graphics_reset_palette();               /* Reset Palette */
    libre();
    ControlPort.params[0] = 1;
    api(5, 38);                                 /* 5,38 : Get Palette */
    printf("Couleur 1 remise : %u %u %u\n", ControlPort.params[1], ControlPort.params[2], ControlPort.params[3]);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleur 1 remise : 255 0 77
Mad Pascal
// Changer une couleur, puis remettre la palette d'origine (groupe 5, fonction 34).
program repalette;
uses crt, neo6502;
var r, g, b: byte;
begin
  NeoSetPalette(1, 1, 2, 3);                    // 5,32
  NeoResetPalette;                              // Reset Palette
  NeoGetPalette(1, r, g, b);                    // 5,38
  writeln('Couleur 1 remise : ', r, ' ', g, ' ', b);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleur 1 remise : 255 0 77
NeoBASIC
10 ' Changer une couleur, puis remettre la palette d'origine (groupe 5, fonction 34)
20 palette 1, 1, 2, 3
30 palette clear
40 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 38 : poke $ff00, 5 : ' 5,38
50 while peek($ff00) : wend : r = peek($ff05) : g = peek($ff06) : b = peek($ff07)
60 print "Couleur 1 remise : ";r;" ";g;" ";b
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleur 1 remise : 255 0 77
Assembleur 65C02 (64tass)
; Changer une couleur, puis remettre la palette d'origine (groupe 5, fonction 34).
        .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 WaitMessage
        lda #1
        sta ControlPort+4          ; couleur 1 := (1, 2, 3)
        sta ControlPort+5
        lda #2
        sta ControlPort+6
        lda #3
        sta ControlPort+7
        ldx #32                    ; 5,32 : Set Palette
        jsr g5
        ldx #34                    ; fonction 34 : Reset Palette
        jsr g5
        lda #1
        sta ControlPort+4
        ldx #38                    ; 5,38 : Get Palette
        jsr g5
        lda ControlPort+5
        sta r
        lda ControlPort+6
        sta v
        lda ControlPort+7
        sta b
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda r
        jsr decimal
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda v
        jsr decimal
        lda #<t4
        ldx #>t4
        jsr ecrire
        lda b
        jsr decimal
        lda #13
        jmp WriteCharacter

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        jmp appel

; 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

r:      .byte 0
v:      .byte 0
b:      .byte 0
t0:     .text "Couleur 1 remise : ", 0
t2:     .text " ", 0
t4:     .text " ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleur 1 remise : 255 0 77

5,35 Set Tilemap Officiel

Désigne la carte de tuiles, en mémoire du 65C02, et le décalage de départ en pixels.

Entrées
OctetsTypeRôle
P0-P1addradresse de la carte : un octet de format, largeur et hauteur en tuiles, puis un numéro de tuile par case, ligne par ligne
P2-P3uint16décalage X dans la carte, en pixels
P4-P5uint16décalage Y dans la carte, en pixels

Sorties : aucune.

La carte reste en mémoire du 65C02 et est relue à chaque tracé (5,8). Sur Trinity, une carte qui déborde de la mémoire est refusée (T-60). En NeoBASIC, tilemap adresse, x, y fait cet appel.

Mots-clés NeoBASIC qui font cet appel : tilemap

Texte de la documentation du firmware (anglais)

Set the current tilemap. Parameters:0,1 is the memory address of the tilemap, and Parameters:2,3,Parameters:4,5 (X,Y) specifies the offset into the tilemap, in units of pixels, of the top-left pixel of the tile.

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

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 const uint8_t carte[] = { 1, 2, 1, 0, 0 };   /* format, largeur 2, hauteur 1, tuiles 0 0 */

/* Choisir une carte de tuiles et la dessiner (groupe 5, fonction 35). */
int main(void) {
    images(1);
    neo_graphics_set_tilemap(carte, 0, 0);      /* 5,35 : Set Tilemap */
    neo_graphics_draw_tilemap(150, 160, 182, 176);   /* 5,8 */
    uint8_t a = neo_graphics_read_pixel(152, 165);
    uint8_t b = neo_graphics_read_pixel(160, 165);
    uint8_t c = neo_graphics_read_pixel(168, 165);
    printf("Couleurs sur la ligne : %u %u %u\n", a, b, c);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleurs sur la ligne : 2 5 2
Mad Pascal
// Choisir une carte de tuiles et la dessiner (groupe 5, fonction 35).
program carte35;
uses crt, neo6502;
var a, b, c: byte;
    carte: array[0..4] of byte = (1, 2, 1, 0, 0);   // format, largeur 2, hauteur 1, tuiles 0 0
    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(1);
  NeoSelectTileMap(word(@carte), 0, 0);         // 5,35 : Set Tilemap
  NeoDrawTileMap(150, 160, 182, 176);           // 5,8
  a := NeoGetPixel(152, 165);
  b := NeoGetPixel(160, 165);
  c := NeoGetPixel(168, 165);
  writeln('Couleurs sur la ligne : ', a, ' ', b, ' ', c);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleurs sur la ligne : 2 5 2
NeoBASIC
10 ' Choisir une carte de tuiles et la dessiner (groupe 5, fonction 35)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 1, 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 m = alloc(8) : poke m, 1 : poke m + 1, 2 : poke m + 2, 1 : poke m + 3, 0 : poke m + 4, 0 : ' carte 2 x 1
40 tilemap m, 0, 0
50 tiledraw 150,160 to 182,176
60 a = point(152,165) : b = point(160,165) : c = point(168,165)
70 print "Couleurs sur la ligne : ";a;" ";b;" ";c
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleurs sur la ligne : 2 5 2
Assembleur 65C02 (64tass)
; Choisir une carte de tuiles et la dessiner (groupe 5, fonction 35).
        .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 WaitMessage
        jsr images
        jsr WaitMessage
        lda #<carte
        sta ControlPort+4          ; P0-P1 : carte
        lda #>carte
        sta ControlPort+5
        stz ControlPort+6          ; P2-P5 : décalage (0, 0)
        stz ControlPort+7
        stz ControlPort+8
        stz ControlPort+9
        ldx #35                    ; 5,35 : Set Tilemap
        jsr g5
        lda #150
        ldy #160
        jsr point1
        lda #182
        ldy #176
        jsr point2
        ldx #8                     ; 5,8 : Draw Tilemap
        jsr g5
        lda #152
        ldy #165
        jsr lire
        sta a
        lda #160
        ldy #165
        jsr lire
        sta b
        lda #168
        ldy #165
        jsr lire
        sta c
        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 #13
        jmp WriteCharacter

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        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, 1, 0, 0             ; en-tête : une tuile
        .fill 252
        .rept 16                   ; 16 lignes : gauche couleur 2, droite couleur 5
        .byte $22, $22, $22, $22, $55, $55, $55, $55
        .endrept
carte:  .byte 1, 2, 1, 0, 0         ; format, largeur 2, hauteur 1, tuiles 0 0
a:      .byte 0
b:      .byte 0
c:      .byte 0
t0:     .text "Couleurs sur la ligne : ", 0
t2:     .text " ", 0
t4:     .text " ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleurs sur la ligne : 2 5 2

5,36 Read Sprite Pixel Officiel

Lit la couleur d'un pixel de la couche des sprites.

Entrées
OctetsTypeRôle
P0-P1int16X du point
P2-P3int16Y du point
Sorties
OctetsTypeRôle
P0uint8couleur du sprite (0 à 15), 0 s'il n'y a pas de sprite à cet endroit ou pas de sprites
erreuruint81 si le point est hors de l'écran

Les sprites occupent les 4 bits hauts de la mémoire d'écran, le fond les 4 bits bas. L'exemple place le sprite 0 (image 16×16, ancré au centre) sur un pixel de fond de couleur 6 : 5,36 lit le sprite, 5,33 le fond. Il efface ensuite les sprites (6,1). En NeoBASIC, spoint(x, y) fait cet appel.

Mots-clés NeoBASIC qui font cet appel : spoint()

Texte de la documentation du firmware (anglais)

Read Pixel from the sprite layer at the screen coordinates specified in Parameters:0,1,Parameters:2,3 (X,Y). When the routine completes, the result will be in Parameter:0. Refer to Section "Pixel Colors" for details.

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 */
}

/* Lire un pixel de sprite et le fond dessous (groupe 5, fonction 36). */
int main(void) {
    images(2);                                  /* un sprite 16x16 */
    neo_graphics_set_color(6);
    neo_graphics_draw_pixel(200, 170);          /* fond : couleur 6 */
    neo_sprite_set(0, 200, 170, 0, 0, 0);       /* 6,2 : sprite 0, image 0 */
    libre();
    xy(0, 200, 170);
    api(5, 36);                                 /* Read Sprite Pixel */
    uint8_t a = ControlPort.params[0];
    uint8_t b = neo_graphics_read_pixel(200, 170);
    neo_sprite_reset();                         /* 6,1 */
    printf("Sprite : %u, fond : %u\n", a, b);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Sprite : 5, fond : 6
Mad Pascal
// Lire un pixel de sprite et le fond dessous (groupe 5, fonction 36).
program spoint;
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
  NeoSetColor(6);
  NeoDrawPixel(200, 170);                       // fond : couleur 6
  NeoUpdateSprite(0, 200, 170, 0, 0, 0);        // 6,2 : sprite 0, image 0
  a := NeoGetSpritePixel(200, 170);             // Read Sprite Pixel
  b := NeoGetPixel(200, 170);
  NeoResetSprites;                              // 6,1
  writeln('Sprite : ', a, ', fond : ', b);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Sprite : 5, fond : 6
NeoBASIC
10 ' Lire un pixel de sprite et le fond dessous (groupe 5, fonction 36)
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 plot 0,0 ink 6 to 200,170 : ' fond : couleur 6
40 sprite 0 image $80 to 200,170 : ' $80 : premier sprite 16x16
50 a = spoint(200,170) : b = point(200,170)
60 sprite clear
70 print "Sprite : ";a;", fond : ";b
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Sprite : 5, fond : 6
Assembleur 65C02 (64tass)
; Lire un pixel de sprite et le fond dessous (groupe 5, fonction 36).
        .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 WaitMessage
        jsr images                 ; un sprite 16x16
        lda #6
        sta ControlPort+4
        ldx #64                    ; 5,64 : couleur 6
        jsr g5
        lda #200
        ldy #170
        jsr point1
        ldx #5                     ; 5,5 : fond
        jsr g5
        stz ControlPort+4          ; P0 : sprite 0
        lda #200
        sta ControlPort+5          ; P1-P2 : X
        stz ControlPort+6
        lda #170
        sta ControlPort+7          ; P3-P4 : Y
        stz ControlPort+8
        stz ControlPort+9          ; P5 : image 0
        stz ControlPort+10         ; P6 : pas de retournement
        stz ControlPort+11         ; P7 : ancre au centre
        lda #6
        ldx #2                     ; 6,2 : Sprite Set
        jsr appel
        lda #200
        ldy #170
        jsr point1
        ldx #36                    ; fonction 36 : Read Sprite Pixel
        jsr g5
        lda ControlPort+4
        sta a
        lda #200
        ldy #170
        jsr lire
        sta b
        lda #6
        ldx #1                     ; 6,1 : Sprite Reset
        jsr appel
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda a
        jsr decimal
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda b
        jsr decimal
        lda #13
        jmp WriteCharacter

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        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 "Sprite : ", 0
t2:     .text ", fond : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Sprite : 5, fond : 6

5,37 Frame Count Officiel

Donne le nombre de balayages d'écran (trames) depuis la mise sous tension.

Entrées : aucune.

Sorties
OctetsTypeRôle
P0-P3uint32nombre de trames

Le compteur change au début de chaque balayage : attendre qu'il change synchronise un programme sur l'écran (c'est ce que fait NeoWaitForVblank en Mad Pascal). L'exemple attend un changement et affiche l'écart. En NeoBASIC, vblanks() fait cet appel.

Mots-clés NeoBASIC qui font cet appel : vblanks()

Texte de la documentation du firmware (anglais)

Deposit into Parameters:0..3, the number of v-blanks (full screen redraws) which have occurred since power-on. This is updated at the start of each v-blank period.

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Attendre la trame suivante (groupe 5, fonction 37). */
int main(void) {
    long t0 = neo_graphics_frame_count();       /* Frame Count */
    long t1;
    do
        t1 = neo_graphics_frame_count();
    while (t1 == t0);
    printf("Trame suivante : ecart %ld\n", t1 - t0);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Trame suivante : ecart 1
Mad Pascal
// Attendre la trame suivante (groupe 5, fonction 37).
program trames;
uses crt, neo6502;
var t0, t1: cardinal;
begin
  t0 := NeoGetVblanks;                          // Frame Count
  repeat
    t1 := NeoGetVblanks;
  until t1 <> t0;
  writeln('Trame suivante : ecart ', t1 - t0);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Trame suivante : ecart 1
NeoBASIC
10 ' Attendre la trame suivante (groupe 5, fonction 37)
20 t0 = vblanks()
30 repeat : t1 = vblanks() : until t1 <> t0
40 print "Trame suivante : ecart ";t1 - t0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Trame suivante : ecart 1
Assembleur 65C02 (64tass)
; Attendre la trame suivante (groupe 5, fonction 37).
        .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 trame
        sta t0
_att:   jsr trame
        cmp t0
        beq _att
        sec
        sbc t0
        pha
        lda #<m
        ldx #>m
        jsr ecrire
        pla
        jsr decimal
        lda #13
        jmp WriteCharacter

; Octet bas du compteur de trames (5,37) dans A.
trame:  jsr WaitMessage
        lda #5
        ldx #37                    ; fonction 37 : Frame Count
        jsr appel
        lda ControlPort+4
        rts

; 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

t0:     .byte 0
m:      .text "Trame suivante : ecart ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Trame suivante : ecart 1

5,38 Get Palette Officiel

Lit les composantes rouge, verte et bleue d'un numéro de la palette.

Entrées
OctetsTypeRôle
P0uint8numéro de couleur
Sorties
OctetsTypeRôle
P1uint8rouge
P2uint8vert
P3uint8bleu

L'exemple lit les couleurs 0 à 2 de la palette d'origine. llvm-mos n'a pas de fonction pour cet appel : l'exemple C le fait directement.

Texte de la documentation du firmware (anglais)

Get the palette colour at the index spcified in Parameter:0. Values are returned in Parameter:1,Parameter:2,Parameter:3 (RGB).

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;
}

/* Lire les trois premières couleurs de la palette (groupe 5, fonction 38). */
int main(void) {
    for (uint8_t c = 0; c < 3; c++) {
        libre();
        ControlPort.params[0] = c;
        api(5, 38);                             /* Get Palette */
        printf("Couleur %u : %u %u %u\n", c, ControlPort.params[1], ControlPort.params[2], ControlPort.params[3]);
    }
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleur 0 : 0 0 0
Couleur 1 : 255 0 0
Couleur 2 : 0 228 54
Mad Pascal
// Lire les trois premières couleurs de la palette (groupe 5, fonction 38).
program litpalette;
uses crt, neo6502;
var c, r, g, b: byte;
begin
  for c := 0 to 2 do
  begin
    NeoGetPalette(c, r, g, b);                  // Get Palette
    writeln('Couleur ', c, ' : ', r, ' ', g, ' ', b);
  end;
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleur 0 : 0 0 0
Couleur 1 : 255 0 0
Couleur 2 : 0 228 54
NeoBASIC
10 ' Lire les trois premieres couleurs de la palette (groupe 5, fonction 38)
20 for c = 0 to 2
30 while peek($ff00) : wend : poke $ff04, c : poke $ff01, 38 : poke $ff00, 5
40 while peek($ff00) : wend : r = peek($ff05) : g = peek($ff06) : b = peek($ff07)
50 print "Couleur ";c;" : ";r;" ";g;" ";b
60 next c
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleur 0 : 0 0 0
Couleur 1 : 255 0 0
Couleur 2 : 0 228 54
Assembleur 65C02 (64tass)
; Lire les trois premières couleurs de la palette (groupe 5, fonction 38).
        .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:  stz c
_suiv:  jsr WaitMessage
        lda c
        sta ControlPort+4          ; P0 : couleur
        lda #5
        ldx #38                    ; fonction 38 : Get Palette
        jsr appel
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda c
        jsr decimal
        lda #<t1
        ldx #>t1
        jsr ecrire
        ldy #5
_rvb:   lda ControlPort,y          ; P1, P2, P3 ($FF05-$FF07)
        jsr decimal
        cpy #7
        beq _fin
        lda #' '
        jsr WriteCharacter
        iny
        bra _rvb
_fin:   lda #13
        jsr WriteCharacter
        inc c
        lda c
        cmp #3
        bne _suiv
        rts

; 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

c:      .byte 0
t0:     .text "Couleur ", 0
t1:     .text " : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Couleur 0 : 0 0 0
Couleur 1 : 255 0 0
Couleur 2 : 0 228 54

5,39 Write Pixel Officiel

Écrit une couleur telle quelle dans un pixel, sans masque ni OU EXCLUSIF.

Entrées
OctetsTypeRôle
P0-P1int16X du point
P2-P3int16Y du point
P4uint8couleur

Sorties : aucune.

Contrairement à 5,5, le résultat ne dépend pas des réglages de 5,1 : l'exemple règle un OU EXCLUSIF (masque $FF, couleur 3) qui changerait un tracé 5,5, puis écrit 9 et relit 9.

Texte de la documentation du firmware (anglais)

Write Pixel index Parameter:4 to the screen coordinate specified in Parameters:0,1,Parameters:2,3 (X,Y).

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Écrire une couleur telle quelle (groupe 5, fonction 39). */
int main(void) {
    neo_graphics_set_defaults(0xFF, 3, 0, 1, 0);   /* 5,1 : OU EXCLUSIF, sans effet ici */
    neo_graphics_write_pixel(210, 170, 9);      /* Write Pixel */
    printf("Pixel ecrit : %u\n", neo_graphics_read_pixel(210, 170));
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel ecrit : 9
Mad Pascal
// Écrire une couleur telle quelle (groupe 5, fonction 39).
program ecrit;
uses crt, neo6502;
var a: byte;
begin
  NeoSetDefaults($FF, 3, 0, 1, 0);              // 5,1 : OU EXCLUSIF, sans effet ici
  NeoWritePixel(210, 170, 9);                   // Write Pixel
  a := NeoGetPixel(210, 170);
  writeln('Pixel ecrit : ', a);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel ecrit : 9
NeoBASIC
10 ' Ecrire une couleur telle quelle (groupe 5, fonction 39)
20 while peek($ff00) : wend
30 poke $ff04, 210 : poke $ff05, 0 : poke $ff06, 170 : poke $ff07, 0 : poke $ff08, 9 : poke $ff01, 39 : poke $ff00, 5
40 while peek($ff00) : wend
50 print "Pixel ecrit : ";point(210,170)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel ecrit : 9
Assembleur 65C02 (64tass)
; Écrire une couleur telle quelle (groupe 5, fonction 39).
        .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 WaitMessage
        lda #$FF
        sta ControlPort+4          ; 5,1 : masque $FF, couleur 3 (sans effet ici)
        lda #3
        sta ControlPort+5
        stz ControlPort+6
        lda #1
        sta ControlPort+7
        stz ControlPort+8
        ldx #1
        jsr g5
        lda #210
        ldy #170
        jsr point1
        lda #9
        sta ControlPort+8          ; P4 : couleur 9
        ldx #39                    ; fonction 39 : Write Pixel
        jsr g5
        lda #210
        ldy #170
        jsr lire
        sta a
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda a
        jsr decimal
        lda #13
        jmp WriteCharacter

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        jmp appel

; 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

a:      .byte 0
t0:     .text "Pixel ecrit : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel ecrit : 9

5,40 Get Late Scanlines Trinity

Donne le nombre de lignes de balayage que le second cœur n'a pas pu produire à temps depuis le dernier changement de mode (diagnostic).

Entrées : aucune.

Sorties
OctetsTypeRôle
P0-P3uint32nombre de lignes en retard

Propre à Trinity (T-32c). Sur la carte, ces lignes apparaissent comme des traînées colorées ; un compteur qui grandit pendant un programme indique un second cœur débordé. Les émulateurs rendent toujours 0 (valeur vérifiée par le banc).

Texte de la documentation du firmware (anglais)

Returns in Parameters:0-3 the number of scanlines the display could not encode in time since the last mode change (Trinity T-32c, Function 5,40, diagnostic : these show as coloured streaks on the board ; 0 in the emulators). A counter that keeps growing while a program runs means the second core is starved.

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;
}

/* Lignes que l'affichage n'a pas pu produire à temps (groupe 5, fonction 40, Trinity). */
int main(void) {
    libre();
    api(5, 40);
    printf("Lignes en retard : %lu\n", (unsigned long)(ControlPort.params[0] | ((uint32_t)ControlPort.params[1] << 8)
                                   | ((uint32_t)ControlPort.params[2] << 16) | ((uint32_t)ControlPort.params[3] << 24)));
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lignes en retard : 0
Mad Pascal
// Lignes que l'affichage n'a pas pu produire à temps (groupe 5, fonction 40, Trinity).
program diag40;
uses crt, neo6502;
var valeur: cardinal;
begin
  NeoWaitMessage;
  NeoSendMessage(5, 40);
  NeoWaitMessage;
  valeur := dwordParams[0];
  writeln('Lignes en retard : ', valeur);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lignes en retard : 0
NeoBASIC
10 ' Lignes que l'affichage n'a pas pu produire à temps (groupe 5, fonction 40, Trinity)
20 while peek($ff00) : wend : poke $ff01, 40 : poke $ff00, 5
22 while peek($ff00) : wend : v0 = peek($ff04) : v1 = peek($ff05) : v2 = peek($ff06) : v = v0 + 256 * v1 + 65536 * v2
24 print "Lignes en retard : ";v
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lignes en retard : 0
Assembleur 65C02 (64tass)
; Lignes que l'affichage n'a pas pu produire à temps (groupe 5, fonction 40, Trinity).
; L'exemple asm n'affiche que l'octet bas de chaque compteur.
        .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 WaitMessage
        lda #5
        ldx #40                    ; fonction 40
        jsr appel
        lda ControlPort+4          ; octet bas
        sta v
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda v
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; 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

v:      .byte 0
t0:     .text "Lignes en retard : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lignes en retard : 0

5,41 Get Bus Stalls Trinity

Donne l'un des compteurs d'incidents du bus du 6502 relevés par les PIO du RP2040 (diagnostic).

Entrées
OctetsTypeRôle
P0uint8compteur : 0 TXSTALL (donnée d'une lecture pas prête à temps), 1 RXSTALL (file des adresses pas vidée à temps), 2 RXUNDER (file vide lue)
Sorties
OctetsTypeRôle
P0-P3uint32valeur du compteur

Propre à Trinity (T-49, T-52). Les émulateurs n'ont pas de PIO et rendent 0 (valeur vérifiée par le banc). La documentation du firmware détaille la signification de chaque compteur.

Texte de la documentation du firmware (anglais)

Returns in Parameters:0-3 one of the PIO fault counters of the 6502 bus, chosen by Parameter:0 on entry (Trinity T-49/T-52, diagnostic ; 0 in the emulators, which have no PIO) : 0 TXSTALL : the data of a read was not ready in time. 1 RXSTALL : the address FIFO was not drained in time. 2 RXUNDER : an EMPTY FIFO was read — the firmware then acts on a stale word and writes a phantom byte at a phantom address into the 6502 memory. This one corrupts the running program. 3 TXOVER : a read reply was pushed into a full FIFO and lost. The state machine generates the 6502 clock, so TXSTALL and RXSTALL merely stretch the processor and are normal while an API command is served ; RXUNDER and TXOVER are not, and any growth there is a fault. Sampled about 95 times a second, so these are windows containing at least one event, not exact counts. Pass $FF in Parameter:0 to reset all four (it then returns TXSTALL).

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;
}

/* Compteurs d'incidents du bus du 6502 (groupe 5, fonction 41, Trinity). */
int main(void) {
    libre();
    ControlPort.params[0] = 0;
    api(5, 41);
    printf("TXSTALL : %lu\n", (unsigned long)(ControlPort.params[0] | ((uint32_t)ControlPort.params[1] << 8)
                                   | ((uint32_t)ControlPort.params[2] << 16) | ((uint32_t)ControlPort.params[3] << 24)));
    libre();
    ControlPort.params[0] = 1;
    api(5, 41);
    printf("RXSTALL : %lu\n", (unsigned long)(ControlPort.params[0] | ((uint32_t)ControlPort.params[1] << 8)
                                   | ((uint32_t)ControlPort.params[2] << 16) | ((uint32_t)ControlPort.params[3] << 24)));
    libre();
    ControlPort.params[0] = 2;
    api(5, 41);
    printf("RXUNDER : %lu\n", (unsigned long)(ControlPort.params[0] | ((uint32_t)ControlPort.params[1] << 8)
                                   | ((uint32_t)ControlPort.params[2] << 16) | ((uint32_t)ControlPort.params[3] << 24)));
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
TXSTALL : 0
RXSTALL : 0
RXUNDER : 0
Mad Pascal
// Compteurs d'incidents du bus du 6502 (groupe 5, fonction 41, Trinity).
program diag41;
uses crt, neo6502;
var valeur: cardinal;
begin
  NeoWaitMessage;
  NeoMessage.params[0] := 0;
  NeoSendMessage(5, 41);
  NeoWaitMessage;
  valeur := dwordParams[0];
  writeln('TXSTALL : ', valeur);
  NeoWaitMessage;
  NeoMessage.params[0] := 1;
  NeoSendMessage(5, 41);
  NeoWaitMessage;
  valeur := dwordParams[0];
  writeln('RXSTALL : ', valeur);
  NeoWaitMessage;
  NeoMessage.params[0] := 2;
  NeoSendMessage(5, 41);
  NeoWaitMessage;
  valeur := dwordParams[0];
  writeln('RXUNDER : ', valeur);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
TXSTALL : 0
RXSTALL : 0
RXUNDER : 0
NeoBASIC
10 ' Compteurs d'incidents du bus du 6502 (groupe 5, fonction 41, Trinity)
20 while peek($ff00) : wend : poke $ff04, 0 : poke $ff01, 41 : poke $ff00, 5
22 while peek($ff00) : wend : v0 = peek($ff04) : v1 = peek($ff05) : v2 = peek($ff06) : v = v0 + 256 * v1 + 65536 * v2
24 print "TXSTALL : ";v
30 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 41 : poke $ff00, 5
32 while peek($ff00) : wend : v0 = peek($ff04) : v1 = peek($ff05) : v2 = peek($ff06) : v = v0 + 256 * v1 + 65536 * v2
34 print "RXSTALL : ";v
40 while peek($ff00) : wend : poke $ff04, 2 : poke $ff01, 41 : poke $ff00, 5
42 while peek($ff00) : wend : v0 = peek($ff04) : v1 = peek($ff05) : v2 = peek($ff06) : v = v0 + 256 * v1 + 65536 * v2
44 print "RXUNDER : ";v
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
TXSTALL : 0
RXSTALL : 0
RXUNDER : 0
Assembleur 65C02 (64tass)
; Compteurs d'incidents du bus du 6502 (groupe 5, fonction 41, Trinity).
; L'exemple asm n'affiche que l'octet bas de chaque compteur.
        .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 WaitMessage
        lda #0
        sta ControlPort+4          ; P0 : compteur choisi
        lda #5
        ldx #41                    ; fonction 41
        jsr appel
        lda ControlPort+4          ; octet bas
        sta v
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda v
        jsr decimal
        lda #13
        jsr WriteCharacter
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : compteur choisi
        lda #5
        ldx #41                    ; fonction 41
        jsr appel
        lda ControlPort+4          ; octet bas
        sta v
        lda #<t1
        ldx #>t1
        jsr ecrire
        lda v
        jsr decimal
        lda #13
        jsr WriteCharacter
        jsr WaitMessage
        lda #2
        sta ControlPort+4          ; P0 : compteur choisi
        lda #5
        ldx #41                    ; fonction 41
        jsr appel
        lda ControlPort+4          ; octet bas
        sta v
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda v
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; 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

v:      .byte 0
t0:     .text "TXSTALL : ", 0
t1:     .text "RXSTALL : ", 0
t2:     .text "RXUNDER : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
TXSTALL : 0
RXSTALL : 0
RXUNDER : 0

5,42 Get Bus Timing Trinity

Donne une mesure de temps (diagnostic, T-50 et T-90) : la plus longue synchronisation, la plus longue commande de l'API, ou une mesure de l'affichage.

Entrées
OctetsTypeRôle
P0uint80 : plus long DSPSync (clavier, USB, clignotement) ; 1 : plus longue commande de l'API ; côté affichage (cœur 1) : 2 plus long traitement d'une ligne, 3 plus long écart entre deux rappels de ligne (nominal : 32 en mode 1, 63 en modes 0 et 2, où chaque ligne est doublée et le rappel n'a lieu qu'une ligne sur deux), 4 nombre de rappels en retard de plus de deux fois cet écart nominal
Sorties
OctetsTypeRôle
P0-P3uint32durée en microsecondes (0 à 3) ou nombre de lignes (4)

Propre à Trinity (T-50). Pendant ces durées, le firmware n'est pas sur le bus du 6502 et l'horloge du processeur est arrêtée : normal pour un appel de l'API, anormal si cela dure. L'émulateur du banc rend 0 ; ses valeurs ne mesurent pas la carte.

Texte de la documentation du firmware (anglais)

Returns in Parameters:0-3 a bus timing measure of Trinity T-50, chosen by Parameter:0 on entry : 0 the longest DSPSync ever seen in microseconds (keyboard, USB task, blink), 1 the longest API command (DSPHandler) ; Trinity T-90 adds the display side, core 1 : 2 the longest scanline callback (conversion of one line into the scan buffer), 3 the longest gap between two scanline callbacks (nominal : 32 in mode 1, whose lines are native, but 63 in modes 0 and 2, whose lines are doubled : the callback runs every other line), 4 the number of callbacks late by more than twice that nominal gap. 0 and 1 are the time the firmware spends away from the 6502 bus : while it is there the PIO stalls and the processor clock stops, which is normal for an API call and pathological when it lasts. Counts of stalls alone (Function 5,41) cannot tell the two apart, hence these. Reset with 5,41 and $FF. 0 in the emulators.

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;
}

/* Durées pendant lesquelles le firmware quitte le bus (groupe 5, fonction 42, Trinity). */
int main(void) {
    libre();
    ControlPort.params[0] = 0;
    api(5, 42);
    printf("DSPSync le plus long : %lu\n", (unsigned long)(ControlPort.params[0] | ((uint32_t)ControlPort.params[1] << 8)
                                   | ((uint32_t)ControlPort.params[2] << 16) | ((uint32_t)ControlPort.params[3] << 24)));
    libre();
    ControlPort.params[0] = 1;
    api(5, 42);
    printf("Commande la plus longue : %lu\n", (unsigned long)(ControlPort.params[0] | ((uint32_t)ControlPort.params[1] << 8)
                                   | ((uint32_t)ControlPort.params[2] << 16) | ((uint32_t)ControlPort.params[3] << 24)));
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
DSPSync le plus long : 0
Commande la plus longue : 0
Mad Pascal
// Durées pendant lesquelles le firmware quitte le bus (groupe 5, fonction 42, Trinity).
program diag42;
uses crt, neo6502;
var valeur: cardinal;
begin
  NeoWaitMessage;
  NeoMessage.params[0] := 0;
  NeoSendMessage(5, 42);
  NeoWaitMessage;
  valeur := dwordParams[0];
  writeln('DSPSync le plus long : ', valeur);
  NeoWaitMessage;
  NeoMessage.params[0] := 1;
  NeoSendMessage(5, 42);
  NeoWaitMessage;
  valeur := dwordParams[0];
  writeln('Commande la plus longue : ', valeur);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
DSPSync le plus long : 0
Commande la plus longue : 0
NeoBASIC
10 ' Durees pendant lesquelles le firmware quitte le bus (groupe 5, fonction 42, Trinity)
20 while peek($ff00) : wend : poke $ff04, 0 : poke $ff01, 42 : poke $ff00, 5
22 while peek($ff00) : wend : v0 = peek($ff04) : v1 = peek($ff05) : v2 = peek($ff06) : v = v0 + 256 * v1 + 65536 * v2
24 print "DSPSync le plus long : ";v
30 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 42 : poke $ff00, 5
32 while peek($ff00) : wend : v0 = peek($ff04) : v1 = peek($ff05) : v2 = peek($ff06) : v = v0 + 256 * v1 + 65536 * v2
34 print "Commande la plus longue : ";v
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
DSPSync le plus long : 0
Commande la plus longue : 0
Assembleur 65C02 (64tass)
; Durées pendant lesquelles le firmware quitte le bus (groupe 5, fonction 42, Trinity).
; L'exemple asm n'affiche que l'octet bas de chaque compteur.
        .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 WaitMessage
        lda #0
        sta ControlPort+4          ; P0 : compteur choisi
        lda #5
        ldx #42                    ; fonction 42
        jsr appel
        lda ControlPort+4          ; octet bas
        sta v
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda v
        jsr decimal
        lda #13
        jsr WriteCharacter
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : compteur choisi
        lda #5
        ldx #42                    ; fonction 42
        jsr appel
        lda ControlPort+4          ; octet bas
        sta v
        lda #<t1
        ldx #>t1
        jsr ecrire
        lda v
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; 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

v:      .byte 0
t0:     .text "DSPSync le plus long : ", 0
t1:     .text "Commande la plus longue : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
DSPSync le plus long : 0
Commande la plus longue : 0

5,64 Set Color Officiel

Choisit la couleur des tracés suivants (masque à 0).

Entrées
OctetsTypeRôle
P0uint8couleur

Sorties : aucune.

Revient à 5,1 avec un masque de 0 et la couleur donnée, sans toucher aux autres réglages. NeoBASIC ne fait pas cet appel (ink c fait 5,1) : l'exemple BASIC l'écrit avec poke.

Texte de la documentation du firmware (anglais)

Set Color Sets the current drawing colour to Parameter:0

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Choisir la couleur de tracé (groupe 5, fonction 64). */
int main(void) {
    neo_graphics_set_color(6);                  /* 5,64 : Set Color */
    neo_graphics_draw_pixel(210, 170);          /* 5,5 */
    uint8_t a = neo_graphics_read_pixel(210, 170);   /* 5,33 */
    uint8_t b = neo_graphics_read_pixel(211, 170);
    printf("Pixel (210, 170) : %u, voisin : %u\n", a, b);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel (210, 170) : 6, voisin : 0
Mad Pascal
// Choisir la couleur de tracé (groupe 5, fonction 64).
program pixel64;
uses crt, neo6502;
var a, b: byte;
begin
  NeoSetColor(6);                               // 5,64 : Set Color
  NeoDrawPixel(210, 170);                       // 5,5
  a := NeoGetPixel(210, 170);                   // 5,33
  b := NeoGetPixel(211, 170);
  writeln('Pixel (210, 170) : ', a, ', voisin : ', b);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel (210, 170) : 6, voisin : 0
NeoBASIC
10 ' Choisir la couleur de trace (groupe 5, fonction 64)
20 while peek($ff00) : wend : poke $ff04, 6 : poke $ff01, 64 : poke $ff00, 5 : ' Set Color
25 plot to 210,170
30 a = point(210,170) : b = point(211,170)
40 print "Pixel (210, 170) : ";a;", voisin : ";b
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel (210, 170) : 6, voisin : 0
Assembleur 65C02 (64tass)
; Choisir la couleur de tracé (groupe 5, fonction 64).
        .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 WaitMessage
        lda #6
        sta ControlPort+4          ; P0 : couleur 6
        ldx #64                    ; 5,64 : Set Color
        jsr g5
        lda #210
        ldy #170
        jsr point1
        ldx #5                     ; 5,5 : Draw Pixel
        jsr g5
        lda #210
        ldy #170
        jsr lire                   ; 5,33 : Read Pixel
        sta a
        lda #211
        ldy #170
        jsr lire
        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

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        jmp appel

; 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

a:      .byte 0
b:      .byte 0
t0:     .text "Pixel (210, 170) : ", 0
t2:     .text ", voisin : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Pixel (210, 170) : 6, voisin : 0

5,65 Set Solid Flag Officiel

Règle le drapeau de remplissage : formes pleines, et fond plein pour le texte et les images.

Entrées
OctetsTypeRôle
P0uint80 : contour (fond transparent) ; non nul : plein

Sorties : aucune.

En NeoBASIC, frame et solid font 5,1 avec ce drapeau.

Texte de la documentation du firmware (anglais)

Set Solid Flag

Sets the solid flag to Parameter:0, which indicates either solid fill (for shapes) or solid background (for images and fonts)

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Le même rectangle en contour puis plein (groupe 5, fonction 65). */
int main(void) {
    neo_graphics_set_color(4);
    neo_graphics_set_solid_flag(0);             /* Set Solid Flag : contour */
    neo_graphics_draw_rectangle(150, 160, 190, 200);
    uint8_t a = neo_graphics_read_pixel(170, 180);   /* centre */
    neo_graphics_set_solid_flag(1);             /* plein */
    neo_graphics_draw_rectangle(150, 160, 190, 200);
    uint8_t b = neo_graphics_read_pixel(170, 180);
    printf("Contour : %u, plein : %u\n", a, b);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Contour : 0, plein : 4
Mad Pascal
// Le même rectangle en contour puis plein (groupe 5, fonction 65).
program remplir;
uses crt, neo6502;
var a, b: byte;
begin
  NeoSetColor(4);
  NeoSetSolidFlag(0);                           // Set Solid Flag : contour
  NeoDrawRect(150, 160, 190, 200);
  a := NeoGetPixel(170, 180);                   // centre
  NeoSetSolidFlag(1);                           // plein
  NeoDrawRect(150, 160, 190, 200);
  b := NeoGetPixel(170, 180);
  writeln('Contour : ', a, ', plein : ', b);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Contour : 0, plein : 4
NeoBASIC
10 ' Le meme rectangle en contour puis plein (groupe 5, fonction 65)
20 while peek($ff00) : wend : poke $ff04, 0 : poke $ff01, 65 : poke $ff00, 5 : ' contour
30 rect 150,160 ink 4 to 190,200 : a = point(170,180)
40 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 65 : poke $ff00, 5 : ' plein
50 rect 150,160 to 190,200 : b = point(170,180)
60 print "Contour : ";a;", plein : ";b
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Contour : 0, plein : 4
Assembleur 65C02 (64tass)
; Le même rectangle en contour puis plein (groupe 5, fonction 65).
        .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 WaitMessage
        lda #4
        sta ControlPort+4
        ldx #64                    ; 5,64 : couleur 4
        jsr g5
        lda #0
        jsr rect                   ; contour
        sta a
        lda #1
        jsr rect                   ; plein
        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

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        jmp appel

; Drapeau A (5,65), rectangle (150, 160)-(190, 200), couleur du centre dans A.
rect:   sta ControlPort+4
        ldx #65                    ; fonction 65 : Set Solid Flag
        jsr g5
        lda #150
        ldy #160
        jsr point1
        lda #190
        ldy #200
        jsr point2
        ldx #3                     ; 5,3 : rectangle
        jsr g5
        lda #170
        ldy #180
        jmp lire

; 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

a:      .byte 0
b:      .byte 0
t0:     .text "Contour : ", 0
t2:     .text ", plein : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Contour : 0, plein : 4

5,66 Set Draw Size Officiel

Choisit la taille (facteur d'agrandissement) des images et du texte.

Entrées
OctetsTypeRôle
P0uint8taille : 1 normale, 2 double…

Sorties : aucune.

Le point lu est à 20 pixels à droite du coin : hors de l'image en taille 1 (16 pixels de large), dans sa moitié droite en taille 2 (32 pixels). La taille 2 sert aussi aux cartes de tuiles 32×32 (5,8). En NeoBASIC, dim n fait 5,1 avec cette taille.

Texte de la documentation du firmware (anglais)

Set Draw Size

Sets the drawing scale for images and fonts to Parameter:0

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

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 */
}

/* Dessiner une image en taille 1 puis 2 (groupe 5, fonction 66). */
int main(void) {
    images(1);
    neo_graphics_set_draw_size(1);             /* 5,66 : Set Draw Size */
    neo_graphics_set_flip_bits(0);             /* 5,67 */
    neo_graphics_draw_image(150, 160, 0);         /* 5,7, image 0 */
    uint8_t a = neo_graphics_read_pixel(170, 165);
    neo_graphics_set_draw_size(2);             /* 5,66 : Set Draw Size */
    neo_graphics_set_flip_bits(0);             /* 5,67 */
    neo_graphics_draw_image(200, 160, 0);         /* 5,7, image 0 */
    uint8_t b = neo_graphics_read_pixel(220, 165);
    printf("Taille 1 : %u, taille 2 : %u\n", a, b);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Taille 1 : 0, taille 2 : 5
Mad Pascal
// Dessiner une image en taille 1 puis 2 (groupe 5, fonction 66).
program image66;
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(1);
  NeoSetDrawSize(1);                            // 5,66 : Set Draw Size
  NeoSetFlip(0);                                // 5,67
  NeoDrawImage(150, 160, 0);                      // 5,7, image 0
  a := NeoGetPixel(170, 165);
  NeoSetDrawSize(2);                            // 5,66 : Set Draw Size
  NeoSetFlip(0);                                // 5,67
  NeoDrawImage(200, 160, 0);                      // 5,7, image 0
  b := NeoGetPixel(220, 165);
  writeln('Taille 1 : ', a, ', ', 'taille 2 : ', b);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Taille 1 : 0, taille 2 : 5
NeoBASIC
10 ' Dessiner une image en taille 1 puis 2 (groupe 5, fonction 66)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 1, 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 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 66 : poke $ff00, 5 : ' taille
31 while peek($ff00) : wend : poke $ff04, 0 : poke $ff01, 67 : poke $ff00, 5 : ' retournement
32 while peek($ff00) : wend : poke $ff04, 150 : poke $ff05, 0 : poke $ff06, 160 : poke $ff07, 0 : poke $ff08, 0 : poke $ff01, 7 : poke $ff00, 5
33 while peek($ff00) : wend : a = point(170,165)
40 while peek($ff00) : wend : poke $ff04, 2 : poke $ff01, 66 : poke $ff00, 5 : ' taille
41 while peek($ff00) : wend : poke $ff04, 0 : poke $ff01, 67 : poke $ff00, 5 : ' retournement
42 while peek($ff00) : wend : poke $ff04, 200 : poke $ff05, 0 : poke $ff06, 160 : poke $ff07, 0 : poke $ff08, 0 : poke $ff01, 7 : poke $ff00, 5
43 while peek($ff00) : wend : b = point(220,165)
50 print "Taille 1 : ";a; ", ";"taille 2 : ";b
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Taille 1 : 0, taille 2 : 5
Assembleur 65C02 (64tass)
; Dessiner une image en taille 1 puis 2 (groupe 5, fonction 66).
        .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 WaitMessage
        jsr images
        lda #1
        sta ControlPort+4
        ldx #66                    ; 5,66 : taille 1
        jsr g5
        lda #0
        sta ControlPort+4
        ldx #67                    ; 5,67 : retournement 0
        jsr g5
        lda #150
        ldy #160
        jsr point1
        stz ControlPort+8          ; P4 : image 0
        ldx #7                     ; 5,7 : Draw Image
        jsr g5
        lda #170
        ldy #165
        jsr lire
        sta a
        lda #2
        sta ControlPort+4
        ldx #66                    ; 5,66 : taille 2
        jsr g5
        lda #0
        sta ControlPort+4
        ldx #67                    ; 5,67 : retournement 0
        jsr g5
        lda #200
        ldy #160
        jsr point1
        stz ControlPort+8          ; P4 : image 0
        ldx #7                     ; 5,7 : Draw Image
        jsr g5
        lda #220
        ldy #165
        jsr lire
        sta b
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda a
        jsr decimal
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda #<t3
        ldx #>t3
        jsr ecrire
        lda b
        jsr decimal
        lda #13
        jmp WriteCharacter

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        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, 1, 0, 0             ; en-tête : une tuile
        .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 "Taille 1 : ", 0
t2:     .text ", ", 0
t3:     .text "taille 2 : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Taille 1 : 0, taille 2 : 5

5,67 Set Flip Bits Officiel

Règle le retournement des images : bit 0 horizontal, bit 1 vertical.

Entrées
OctetsTypeRôle
P0uint8bit 0 : miroir horizontal ; bit 1 : miroir vertical

Sorties : aucune.

L'image a sa moitié gauche en couleur 2 : retournée horizontalement, elle y montre la couleur 5. En NeoBASIC, image n, retournement to x,y fait 5,1 avec ce réglage.

Texte de la documentation du firmware (anglais)

Set Flip Bits Sets the flip bits for drawing images. Bit 0 set causes a horizontal flip, bit 1 set causes a vertical flip.

C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

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 */
}

/* Dessiner une image retournée (groupe 5, fonction 67). */
int main(void) {
    images(1);
    neo_graphics_set_draw_size(1);             /* 5,66 */
    neo_graphics_set_flip_bits(0);             /* 5,67 : Set Flip Bits */
    neo_graphics_draw_image(150, 160, 0);         /* 5,7, image 0 */
    uint8_t a = neo_graphics_read_pixel(152, 165);
    neo_graphics_set_draw_size(1);             /* 5,66 */
    neo_graphics_set_flip_bits(1);             /* 5,67 : Set Flip Bits */
    neo_graphics_draw_image(200, 160, 0);         /* 5,7, image 0 */
    uint8_t b = neo_graphics_read_pixel(202, 165);
    printf("Normale : %u, retournee : %u\n", a, b);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Normale : 2, retournee : 5
Mad Pascal
// Dessiner une image retournée (groupe 5, fonction 67).
program image67;
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(1);
  NeoSetDrawSize(1);                            // 5,66
  NeoSetFlip(0);                                // 5,67 : Set Flip Bits
  NeoDrawImage(150, 160, 0);                      // 5,7, image 0
  a := NeoGetPixel(152, 165);
  NeoSetDrawSize(1);                            // 5,66
  NeoSetFlip(1);                                // 5,67 : Set Flip Bits
  NeoDrawImage(200, 160, 0);                      // 5,7, image 0
  b := NeoGetPixel(202, 165);
  writeln('Normale : ', a, ', ', 'retournee : ', b);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Normale : 2, retournee : 5
NeoBASIC
10 ' Dessiner une image retournee (groupe 5, fonction 67)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 1, 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 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 66 : poke $ff00, 5 : ' taille
31 while peek($ff00) : wend : poke $ff04, 0 : poke $ff01, 67 : poke $ff00, 5 : ' retournement
32 while peek($ff00) : wend : poke $ff04, 150 : poke $ff05, 0 : poke $ff06, 160 : poke $ff07, 0 : poke $ff08, 0 : poke $ff01, 7 : poke $ff00, 5
33 while peek($ff00) : wend : a = point(152,165)
40 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 66 : poke $ff00, 5 : ' taille
41 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 67 : poke $ff00, 5 : ' retournement
42 while peek($ff00) : wend : poke $ff04, 200 : poke $ff05, 0 : poke $ff06, 160 : poke $ff07, 0 : poke $ff08, 0 : poke $ff01, 7 : poke $ff00, 5
43 while peek($ff00) : wend : b = point(202,165)
50 print "Normale : ";a; ", ";"retournee : ";b
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Normale : 2, retournee : 5
Assembleur 65C02 (64tass)
; Dessiner une image retournée (groupe 5, fonction 67).
        .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 WaitMessage
        jsr images
        lda #1
        sta ControlPort+4
        ldx #66                    ; 5,66 : taille 1
        jsr g5
        lda #0
        sta ControlPort+4
        ldx #67                    ; 5,67 : retournement 0
        jsr g5
        lda #150
        ldy #160
        jsr point1
        stz ControlPort+8          ; P4 : image 0
        ldx #7                     ; 5,7 : Draw Image
        jsr g5
        lda #152
        ldy #165
        jsr lire
        sta a
        lda #1
        sta ControlPort+4
        ldx #66                    ; 5,66 : taille 1
        jsr g5
        lda #1
        sta ControlPort+4
        ldx #67                    ; 5,67 : retournement 1
        jsr g5
        lda #200
        ldy #160
        jsr point1
        stz ControlPort+8          ; P4 : image 0
        ldx #7                     ; 5,7 : Draw Image
        jsr g5
        lda #202
        ldy #165
        jsr lire
        sta b
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda a
        jsr decimal
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda #<t3
        ldx #>t3
        jsr ecrire
        lda b
        jsr decimal
        lda #13
        jmp WriteCharacter

; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
        stz ControlPort+5
        sty ControlPort+6
        stz ControlPort+7
        rts
point2: sta ControlPort+8
        stz ControlPort+9
        sty ControlPort+10
        stz ControlPort+11
        rts

; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire:   pha
        jsr WaitMessage
        pla
        jsr point1
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

; Appel du groupe 5, fonction X.
g5:     lda #5
        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, 1, 0, 0             ; en-tête : une tuile
        .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 "Normale : ", 0
t2:     .text ", ", 0
t3:     .text "retournee : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Normale : 2, retournee : 5

← L'API du Neo6502