Tachibana
Language: English

Group 32 — QuickDraw Trinity

32,1 Init Graf · 32,2 Set Clip · 32,3 Get Clip · 32,4 Set Pen Colour · 32,5 Move To · 32,6 Get Pen · 32,7 Frame Rect · 32,8 Paint Rect · 32,9 Erase Rect · 32,10 Invert Rect · 32,11 Line To · 32,12 Set Pattern · 32,13 Fill Rect · 32,14 Copy Bits · 32,15 Set Font · 32,16 Draw String · 32,17 Text Width · 32,18 Get Font Info · 32,19 Toolbox Reset

QuickDraw is the drawing layer of the Trinity toolbox (groups 32 to 38). It draws on the draw page, below the sprites, and always inside a clip rectangle.

Structures live in 6502 RAM and are passed by address. A Rect is 8 bytes: left, top, right, bottom, as signed 16-bit values; right and bottom are excluded (100, 100, 104, 102 covers x 100 to 103 and y 100 to 101).

The pen has a position and a colour; 32,1 puts it back at (0, 0), colour 15, with the clip on the whole screen and a solid pattern. The examples clear the screen, draw, then read the pixels back with 5,33.

32,1 Init Graf Trinity

Resets QuickDraw: clip on the whole screen, pen at (0, 0), colour 15, solid pattern.

Inputs: none.

Outputs: none.

Nothing is drawn or erased. A program may call it at any time to start again from a known state; the examples of this group call it at the start and at the end. The example first moves the pen and changes its colour, then reads the state back with 32,6 and 32,3. NeoBASIC has no keyword for this call.

Firmware documentation text

Toolbox (Trinity, T-12, ADR-01 of the fork). Resets the drawing port : the clip rectangle is the whole screen, the pen is at (0,0) with colour 15. Structures of this group live in 6502 RAM and are passed by address : a Rect is left, top, right, bottom as signed 16 bit values, right and bottom exclusive. Drawing is always clipped to the clip rectangle and goes to the draw page, ignoring the sprite layer.

C (llvm-mos)
/* Remettre QuickDraw dans son état de départ (groupe 32, fonction 1, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static int16_t plume_x, plume_y;
static uint8_t plume_c;

static void get_pen(void) {                     /* 32,6 Get Pen */
    libre();
    qd(6);
    plume_x = ControlPort.params[0] | ControlPort.params[1] << 8;
    plume_y = ControlPort.params[2] | ControlPort.params[3] << 8;
    plume_c = ControlPort.params[4];
}

static Rect clip;
static void get_clip(void) {                    /* 32,3 Get Clip : écrit le rectangle de découpe dans clip */
    qd_rect(3, &clip);
}

int main(void) {
    couleur(5);                                 /* un état quelconque : plume en (10, 20), couleur 5 */
    qd_xy(5, 10, 20);
    init_graf();                                /* Init Graf */
    get_pen();
    get_clip();
    printf("Plume : %d, %d, couleur %u\n", plume_x, plume_y, plume_c);
    printf("Decoupe : %d, %d, %d, %d\n", clip.g, clip.h, clip.d, clip.b);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 0, 0, couleur 15
Decoupe : 0, 0, 320, 240
Mad Pascal
// Remettre QuickDraw dans son état de départ (groupe 32, fonction 1, Trinity).
program qd1;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

var plume_x, plume_y: smallint;
    plume_c: byte;

procedure get_pen;                              // 32,6 Get Pen
begin
  NeoWaitMessage;
  qd(6);
  plume_x := smallint(wordParams[0]);
  plume_y := smallint(wordParams[1]);
  plume_c := NeoMessage.params[4];
end;

var clip: Rect;
procedure get_clip;                             // 32,3 Get Clip : écrit le rectangle de découpe dans clip
begin
  qd_rect(3, @clip);
end;

begin
  couleur(5);                                   // un état quelconque : plume en (10, 20), couleur 5
  qd_xy(5, 10, 20);
  init_graf;                                    // Init Graf
  get_pen;
  get_clip;
  writeln('Plume : ', plume_x, ', ', plume_y, ', couleur ', plume_c);
  writeln('Decoupe : ', clip.g, ', ', clip.h, ', ', clip.d, ', ', clip.b);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 0, 0, couleur 15
Decoupe : 0, 0, 320, 240
NeoBASIC
10 ' Remettre QuickDraw dans son etat de depart (groupe 32, fonction 1, Trinity)
20 k = alloc(8)
30 c = 5 : gosub 9300 : x = 10 : y = 20 : f = 5 : gosub 9200 : ' un etat quelconque : plume en (10, 20), couleur 5
40 gosub 9400 : ' Init Graf
50 gosub 9500 : gosub 9600
60 print "Plume : ";px;", ";py;", couleur ";pc
70 print "Decoupe : ";cg;", ";ch;", ";cd;", ";cb
80 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
9500 ' 32,6 Get Pen : px, py, pc
9510 while peek($ff00) : wend : f = 6 : gosub 9110
9520 px = deek($ff04) : py = deek($ff06) : pc = peek($ff08)
9530 if px > 32767 then px = px - 65536
9540 if py > 32767 then py = py - 65536
9550 return
9600 ' 32,3 Get Clip dans le Rect k ; valeurs dans cg, ch, cd, cb
9610 a = k : f = 3 : gosub 9000
9620 cg = deek(k) : ch = deek(k + 2) : cd = deek(k + 4) : cb = deek(k + 6)
9630 return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 0, 0, couleur 15
Decoupe : 0, 0, 320, 240
65C02 assembly (64tass)
; Remettre QuickDraw dans son état de départ (groupe 32, fonction 1, 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 #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
                                   ; un état quelconque : plume en (10, 20), couleur 5
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #<b4
        ldx #>b4
        jsr envoi
        ldx #4
_c3:   lda ControlPort+4,x
        sta pen,x
        dex
        bpl _c3
        lda #<b5
        ldx #>b5
        jsr envoi
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda pen
        ldx pen+1
        jsr dec16
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda pen+2
        ldx pen+2+1
        jsr dec16
        lda #<t8
        ldx #>t8
        jsr ecrire
        lda pen+4
        jsr decimal
        lda #13
        jsr WriteCharacter
        lda #<t9
        ldx #>t9
        jsr ecrire
        lda k
        ldx k+1
        jsr dec16
        lda #<t10
        ldx #>t10
        jsr ecrire
        lda k+2
        ldx k+2+1
        jsr dec16
        lda #<t11
        ldx #>t11
        jsr ecrire
        lda k+4
        ldx k+4+1
        jsr dec16
        lda #<t12
        ldx #>t12
        jsr ecrire
        lda k+6
        ldx k+6+1
        jsr dec16
        lda #13
        jsr WriteCharacter
        rts

b0:     .byte 32, 4, 1, 5          ; 32,4 : Set Pen Colour
b1:     .byte 32, 5, 4             ; 32,5 : Move To
        .word 10, 20
b2:     .byte 32, 1, 0             ; 32,1 : Init Graf
b4:     .byte 32, 6, 0             ; 32,6 : Get Pen
pen:    .fill 5                    ; x, y (16 bits), couleur
b5:     .byte 32, 3, 2             ; 32,3 : Get Clip
        .word k
k:      .fill 8
t6:     .text "Plume : ", 0
t7:     .text ", ", 0
t8:     .text ", couleur ", 0
t9:     .text "Decoupe : ", 0
t10:    .text ", ", 0
t11:    .text ", ", 0
t12:    .text ", ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 0, 0, couleur 15
Decoupe : 0, 0, 320, 240

32,2 Set Clip Trinity

Restricts all QuickDraw drawing to the given rectangle, brought back within the screen edges.

Inputs
BytesTypeMeaning
P0-P1addraddress of the Rect
Outputs
BytesTypeMeaning
erreuruint81 if the rectangle is inverted (right before left or bottom before top) or outside RAM

The example sets a zone from 100 to 110, then paints a larger rectangle: only the inside of the zone is painted (pixel (95, 95) stays 0). An inverted rectangle is refused. NeoBASIC has no keyword for this call.

Firmware documentation text

Sets the clip rectangle to the Rect at Parameters:0,1, intersected with the screen. Error if the Rect is inverted or its address is not in RAM.

C (llvm-mos)
/* Limiter le dessin à un rectangle (groupe 32, fonction 2, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static Rect zone = {100, 100, 110, 110}, grand = {90, 90, 120, 120}, envers = {50, 50, 40, 40};

int main(void) {
    putchar(12);                                /* écran effacé : on relit des pixels */
    init_graf();
    qd_rect(2, &zone);                          /* Set Clip : rien ne se dessine hors de zone */
    couleur(4);
    qd_rect(8, &grand);                         /* 32,8 : peint un rectangle plus grand */
    uint8_t dehors = px(95, 95), dedans = px(105, 105);
    uint8_t e = qd_rect(2, &envers);            /* droite < gauche : refusé */
    init_graf();                                /* rend tout l'écran au dessin */
    printf("Hors de la zone : %u, dedans : %u\n", dehors, dedans);
    printf("Rectangle a l'envers : erreur %u\n", e);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Hors de la zone : 0, dedans : 4
Rectangle a l'envers : erreur 1
Mad Pascal
// Limiter le dessin à un rectangle (groupe 32, fonction 2, Trinity).
program qd2;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

var zone, grand, envers: Rect;
    dehors, dedans, e: byte;
begin
  write(chr(12));                               // écran effacé : on relit des pixels
  zone.g := 100; zone.h := 100; zone.d := 110; zone.b := 110;
  grand.g := 90; grand.h := 90; grand.d := 120; grand.b := 120;
  envers.g := 50; envers.h := 50; envers.d := 40; envers.b := 40;
  init_graf;
  qd_rect(2, @zone);                            // Set Clip : rien ne se dessine hors de zone
  couleur(4);
  qd_rect(8, @grand);                           // 32,8 : peint un rectangle plus grand
  dehors := NeoGetPixel(95, 95);
  dedans := NeoGetPixel(105, 105);
  e := qd_rect(2, @envers);                     // droite < gauche : refusé
  init_graf;                                    // rend tout l'écran au dessin
  writeln('Hors de la zone : ', dehors, ', dedans : ', dedans);
  writeln('Rectangle a l''envers : erreur ', e);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Hors de la zone : 0, dedans : 4
Rectangle a l'envers : erreur 1
NeoBASIC
10 ' Limiter le dessin a un rectangle (groupe 32, fonction 2, Trinity)
20 cls : ' ecran efface : on relit des pixels
30 z = alloc(8) : q = z : g = 100 : h = 100 : d = 110 : b = 110 : gosub 8000
40 gr = alloc(8) : q = gr : g = 90 : h = 90 : d = 120 : b = 120 : gosub 8000
50 ev = alloc(8) : q = ev : g = 50 : h = 50 : d = 40 : b = 40 : gosub 8000
60 gosub 9400
70 a = z : f = 2 : gosub 9000 : ' Set Clip : rien ne se dessine hors de la zone
80 c = 4 : gosub 9300 : a = gr : f = 8 : gosub 9000 : ' 32,8 : peint un rectangle plus grand
90 de = point(95, 95) : dd = point(105, 105)
100 a = ev : f = 2 : gosub 9000 : e2 = e : ' droite < gauche : refuse
110 gosub 9400 : ' rend tout l'ecran au dessin
120 print "Hors de la zone : ";de;", dedans : ";dd
130 print "Rectangle a l'envers : erreur ";e2
140 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Hors de la zone : 0, dedans : 4
Rectangle a l'envers : erreur 1
65C02 assembly (64tass)
; Limiter le dessin à un rectangle (groupe 32, fonction 2, 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 #12                    ; écran effacé : on relit des pixels
        jsr WriteCharacter
        lda #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #<b3
        ldx #>b3
        jsr envoi
        lda #95
        ldy #95
        jsr pixel
        sta de
        lda #105
        ldy #105
        jsr pixel
        sta dd
        lda #<b4
        ldx #>b4
        jsr envoi
        lda ControlPort+2
        sta e2
        lda #<b5
        ldx #>b5
        jsr envoi
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda de
        jsr decimal
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda dd
        jsr decimal
        lda #13
        jsr WriteCharacter
        lda #<t8
        ldx #>t8
        jsr ecrire
        lda e2
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel:  pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0-P1 : X
        stz ControlPort+5
        sty ControlPort+6          ; P2-P3 : Y
        stz ControlPort+7
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

z:      .word 100, 100, 110, 110          ; gauche, haut, droite, bas (droite et bas exclus)
gr:     .word 90, 90, 120, 120          ; gauche, haut, droite, bas (droite et bas exclus)
ev:     .word 50, 50, 40, 40          ; gauche, haut, droite, bas (droite et bas exclus)
b0:     .byte 32, 1, 0             ; 32,1 : Init Graf
b1:     .byte 32, 2, 2             ; 32,2 : Set Clip, rien ne se dessine hors de la zone
        .word z
b2:     .byte 32, 4, 1, 4          ; 32,4 : Set Pen Colour
b3:     .byte 32, 8, 2             ; 32,8 : peint un rectangle plus grand
        .word gr
de:     .byte 0
dd:     .byte 0
b4:     .byte 32, 2, 2             ; droite < gauche : refusé
        .word ev
e2:     .byte 0
b5:     .byte 32, 1, 0             ; rend tout l'écran au dessin
t6:     .text "Hors de la zone : ", 0
t7:     .text ", dedans : ", 0
t8:     .text "Rectangle a l'envers : erreur ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Hors de la zone : 0, dedans : 4
Rectangle a l'envers : erreur 1

32,3 Get Clip Trinity

Writes the current clip rectangle into the given Rect.

Inputs
BytesTypeMeaning
P0-P1addraddress of the Rect to fill

Outputs: none.

The clip read back is the one really in force: 32,2 has intersected it with the screen. The example asks for -10, -10, 500, 50 and reads back 0, 0, 320, 50. NeoBASIC has no keyword for this call.

Firmware documentation text

Writes the current clip rectangle into the Rect at Parameters:0,1.

C (llvm-mos)
/* Relire le rectangle de découpe (groupe 32, fonction 3, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static Rect clip;
static void get_clip(void) {                    /* 32,3 Get Clip : écrit le rectangle de découpe dans clip */
    qd_rect(3, &clip);
}

static Rect demande = {-10, -10, 500, 50};

int main(void) {
    init_graf();
    qd_rect(2, &demande);                       /* 32,2 : déborde de l'écran à gauche, en haut et à droite */
    get_clip();                                 /* Get Clip */
    init_graf();
    printf("Decoupe : %d, %d, %d, %d\n", clip.g, clip.h, clip.d, clip.b);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Decoupe : 0, 0, 320, 50
Mad Pascal
// Relire le rectangle de découpe (groupe 32, fonction 3, Trinity).
program qd3;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

var clip: Rect;
procedure get_clip;                             // 32,3 Get Clip : écrit le rectangle de découpe dans clip
begin
  qd_rect(3, @clip);
end;

var demande: Rect;
begin
  demande.g := -10; demande.h := -10; demande.d := 500; demande.b := 50;
  init_graf;
  qd_rect(2, @demande);                         // 32,2 : déborde de l'écran à gauche, en haut et à droite
  get_clip;                                     // Get Clip
  init_graf;
  writeln('Decoupe : ', clip.g, ', ', clip.h, ', ', clip.d, ', ', clip.b);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Decoupe : 0, 0, 320, 50
NeoBASIC
10 ' Relire le rectangle de decoupe (groupe 32, fonction 3, Trinity)
20 k = alloc(8) : q = alloc(8) : g = -10 : h = -10 : d = 500 : b = 50 : gosub 8000
30 gosub 9400
40 a = q : f = 2 : gosub 9000 : ' 32,2 : deborde de l'ecran a gauche, en haut et a droite
50 gosub 9600 : ' Get Clip
60 gosub 9400
70 print "Decoupe : ";cg;", ";ch;", ";cd;", ";cb
80 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
9600 ' 32,3 Get Clip dans le Rect k ; valeurs dans cg, ch, cd, cb
9610 a = k : f = 3 : gosub 9000
9620 cg = deek(k) : ch = deek(k + 2) : cd = deek(k + 4) : cb = deek(k + 6)
9630 return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Decoupe : 0, 0, 320, 50
65C02 assembly (64tass)
; Relire le rectangle de découpe (groupe 32, fonction 3, 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 #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #<b3
        ldx #>b3
        jsr envoi
        lda #<t4
        ldx #>t4
        jsr ecrire
        lda k
        ldx k+1
        jsr dec16
        lda #<t5
        ldx #>t5
        jsr ecrire
        lda k+2
        ldx k+2+1
        jsr dec16
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda k+4
        ldx k+4+1
        jsr dec16
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda k+6
        ldx k+6+1
        jsr dec16
        lda #13
        jsr WriteCharacter
        rts

q:      .word 65526, 65526, 500, 50          ; gauche, haut, droite, bas (droite et bas exclus)
k:      .fill 8
b0:     .byte 32, 1, 0             ; 32,1 : Init Graf
b1:     .byte 32, 2, 2             ; 32,2 : déborde de l'écran à gauche, en haut et à droite
        .word q
b2:     .byte 32, 3, 2             ; Get Clip
        .word k
b3:     .byte 32, 1, 0             ; 32,1 : Init Graf
t4:     .text "Decoupe : ", 0
t5:     .text ", ", 0
t6:     .text ", ", 0
t7:     .text ", ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Decoupe : 0, 0, 320, 50

32,4 Set Pen Colour Trinity

Selects the pen colour (palette index), used by 32,7, 32,8, 32,11, 32,13 and 32,16.

Inputs
BytesTypeMeaning
P0uint8colour (palette index)

Outputs: none.

The example selects colour 9, paints a rectangle, then reads back a pixel and the pen (32,6). NeoBASIC has no keyword for this call.

Firmware documentation text

Sets the pen colour (palette index) used by Frame Rect and Paint Rect to Parameter:0.

C (llvm-mos)
/* Choisir la couleur de la plume (groupe 32, fonction 4, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static int16_t plume_x, plume_y;
static uint8_t plume_c;

static void get_pen(void) {                     /* 32,6 Get Pen */
    libre();
    qd(6);
    plume_x = ControlPort.params[0] | ControlPort.params[1] << 8;
    plume_y = ControlPort.params[2] | ControlPort.params[3] << 8;
    plume_c = ControlPort.params[4];
}

static Rect r = {100, 100, 104, 104};

int main(void) {
    putchar(12);
    init_graf();
    couleur(9);                                 /* Set Pen Colour */
    qd_rect(8, &r);                             /* 32,8 peint dans cette couleur */
    uint8_t p = px(101, 101);
    get_pen();
    init_graf();
    printf("Pixel : %u, plume : %u\n", p, plume_c);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Pixel : 9, plume : 9
Mad Pascal
// Choisir la couleur de la plume (groupe 32, fonction 4, Trinity).
program qd4;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

var plume_x, plume_y: smallint;
    plume_c: byte;

procedure get_pen;                              // 32,6 Get Pen
begin
  NeoWaitMessage;
  qd(6);
  plume_x := smallint(wordParams[0]);
  plume_y := smallint(wordParams[1]);
  plume_c := NeoMessage.params[4];
end;

var r: Rect;
    p: byte;
begin
  write(chr(12));
  r.g := 100; r.h := 100; r.d := 104; r.b := 104;
  init_graf;
  couleur(9);                                   // Set Pen Colour
  qd_rect(8, @r);                               // 32,8 peint dans cette couleur
  p := NeoGetPixel(101, 101);
  get_pen;
  init_graf;
  writeln('Pixel : ', p, ', plume : ', plume_c);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Pixel : 9, plume : 9
NeoBASIC
10 ' Choisir la couleur de la plume (groupe 32, fonction 4, Trinity)
20 cls : q = alloc(8) : g = 100 : h = 100 : d = 104 : b = 104 : gosub 8000
30 gosub 9400
40 c = 9 : gosub 9300 : ' Set Pen Colour
50 a = q : f = 8 : gosub 9000 : ' 32,8 peint dans cette couleur
60 p = point(101, 101) : gosub 9500
70 gosub 9400
80 print "Pixel : ";p;", plume : ";pc
90 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
9500 ' 32,6 Get Pen : px, py, pc
9510 while peek($ff00) : wend : f = 6 : gosub 9110
9520 px = deek($ff04) : py = deek($ff06) : pc = peek($ff08)
9530 if px > 32767 then px = px - 65536
9540 if py > 32767 then py = py - 65536
9550 return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Pixel : 9, plume : 9
65C02 assembly (64tass)
; Choisir la couleur de la plume (groupe 32, fonction 4, 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 #12                    ; écran effacé : on relit des pixels
        jsr WriteCharacter
        lda #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #101
        ldy #101
        jsr pixel
        sta px
        lda #<b4
        ldx #>b4
        jsr envoi
        ldx #4
_c3:   lda ControlPort+4,x
        sta pen,x
        dex
        bpl _c3
        lda #<b5
        ldx #>b5
        jsr envoi
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda px
        jsr decimal
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda pen+4
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel:  pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0-P1 : X
        stz ControlPort+5
        sty ControlPort+6          ; P2-P3 : Y
        stz ControlPort+7
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

q:      .word 100, 100, 104, 104          ; gauche, haut, droite, bas (droite et bas exclus)
b0:     .byte 32, 1, 0             ; 32,1 : Init Graf
b1:     .byte 32, 4, 1, 9          ; Set Pen Colour
b2:     .byte 32, 8, 2             ; 32,8 peint dans cette couleur
        .word q
px:     .byte 0
b4:     .byte 32, 6, 0             ; 32,6 : Get Pen
pen:    .fill 5                    ; x, y (16 bits), couleur
b5:     .byte 32, 1, 0             ; 32,1 : Init Graf
t6:     .text "Pixel : ", 0
t7:     .text ", plume : ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Pixel : 9, plume : 9

32,5 Move To Trinity

Moves the pen without drawing anything.

Inputs
BytesTypeMeaning
P0-P1int16X (signed)
P2-P3int16Y (signed)

Outputs: none.

The example puts the pen at (30, 40): the pixel stays 0; the line of 32,11 then starts from there. NeoBASIC has no keyword for this call.

Firmware documentation text

Moves the pen to Parameters:0,1 (X) and Parameters:2,3 (Y), signed 16 bit, without drawing.

C (llvm-mos)
/* Déplacer la plume sans dessiner (groupe 32, fonction 5, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static int16_t plume_x, plume_y;
static uint8_t plume_c;

static void get_pen(void) {                     /* 32,6 Get Pen */
    libre();
    qd(6);
    plume_x = ControlPort.params[0] | ControlPort.params[1] << 8;
    plume_y = ControlPort.params[2] | ControlPort.params[3] << 8;
    plume_c = ControlPort.params[4];
}

int main(void) {
    putchar(12);
    init_graf();
    qd_xy(5, 30, 40);                           /* Move To : rien n'est dessiné */
    get_pen();
    int16_t x = plume_x, y = plume_y;
    uint8_t avant = px(30, 40);
    qd_xy(11, 60, 40);                          /* 32,11 : trait depuis la plume */
    uint8_t trait = px(45, 40);
    init_graf();
    printf("Plume : %d, %d ; pixel %u, puis trait : %u\n", x, y, avant, trait);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 30, 40 ; pixel 0, puis trait : 15
Mad Pascal
// Déplacer la plume sans dessiner (groupe 32, fonction 5, Trinity).
program qd5;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

var plume_x, plume_y: smallint;
    plume_c: byte;

procedure get_pen;                              // 32,6 Get Pen
begin
  NeoWaitMessage;
  qd(6);
  plume_x := smallint(wordParams[0]);
  plume_y := smallint(wordParams[1]);
  plume_c := NeoMessage.params[4];
end;

var x, y: smallint;
    avant, trait: byte;
begin
  write(chr(12));
  init_graf;
  qd_xy(5, 30, 40);                             // Move To : rien n'est dessiné
  get_pen;
  x := plume_x;
  y := plume_y;
  avant := NeoGetPixel(30, 40);
  qd_xy(11, 60, 40);                            // 32,11 : trait depuis la plume
  trait := NeoGetPixel(45, 40);
  init_graf;
  writeln('Plume : ', x, ', ', y, ' ; pixel ', avant, ', puis trait : ', trait);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 30, 40 ; pixel 0, puis trait : 15
NeoBASIC
10 ' Deplacer la plume sans dessiner (groupe 32, fonction 5, Trinity)
20 cls : gosub 9400
30 x = 30 : y = 40 : f = 5 : gosub 9200 : ' Move To : rien n'est dessine
40 gosub 9500 : xx = px : yy = py : av = point(30, 40)
50 x = 60 : y = 40 : f = 11 : gosub 9200 : ' 32,11 : trait depuis la plume
60 tr = point(45, 40)
70 gosub 9400
80 print "Plume : ";xx;", ";yy;" ; pixel ";av;", puis trait : ";tr
90 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
9500 ' 32,6 Get Pen : px, py, pc
9510 while peek($ff00) : wend : f = 6 : gosub 9110
9520 px = deek($ff04) : py = deek($ff06) : pc = peek($ff08)
9530 if px > 32767 then px = px - 65536
9540 if py > 32767 then py = py - 65536
9550 return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 30, 40 ; pixel 0, puis trait : 15
65C02 assembly (64tass)
; Déplacer la plume sans dessiner (groupe 32, fonction 5, 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 #12                    ; écran effacé : on relit des pixels
        jsr WriteCharacter
        lda #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b3
        ldx #>b3
        jsr envoi
        ldx #4
_c2:   lda ControlPort+4,x
        sta pen,x
        dex
        bpl _c2
        lda #30
        ldy #40
        jsr pixel
        sta av
        lda #<b4
        ldx #>b4
        jsr envoi
        lda #45
        ldy #40
        jsr pixel
        sta tr
        lda #<b5
        ldx #>b5
        jsr envoi
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda pen
        ldx pen+1
        jsr dec16
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda pen+2
        ldx pen+2+1
        jsr dec16
        lda #<t8
        ldx #>t8
        jsr ecrire
        lda av
        jsr decimal
        lda #<t9
        ldx #>t9
        jsr ecrire
        lda tr
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel:  pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0-P1 : X
        stz ControlPort+5
        sty ControlPort+6          ; P2-P3 : Y
        stz ControlPort+7
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

b0:     .byte 32, 1, 0             ; 32,1 : Init Graf
b1:     .byte 32, 5, 4             ; Move To : rien n'est dessiné
        .word 30, 40
b3:     .byte 32, 6, 0             ; 32,6 : Get Pen
pen:    .fill 5                    ; x, y (16 bits), couleur
av:     .byte 0
b4:     .byte 32, 11, 4            ; 32,11 : Line To
        .word 60, 40
tr:     .byte 0
b5:     .byte 32, 1, 0             ; 32,1 : Init Graf
t6:     .text "Plume : ", 0
t7:     .text ", ", 0
t8:     .text " ; pixel ", 0
t9:     .text ", puis trait : ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 30, 40 ; pixel 0, puis trait : 15

32,6 Get Pen Trinity

Returns the pen position and colour.

Inputs: none.

Outputs
BytesTypeMeaning
P0-P1int16pen X
P2-P3int16pen Y
P4uint8pen colour

After 32,11, the pen is at the end of the line: the example draws from (10, 50) to (70, 50) in colour 3. NeoBASIC has no keyword for this call.

Firmware documentation text

Returns the pen position in Parameters:0,1 (X) and Parameters:2,3 (Y) and the pen colour in Parameter:4.

C (llvm-mos)
/* Lire la position et la couleur de la plume (groupe 32, fonction 6, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static int16_t plume_x, plume_y;
static uint8_t plume_c;

static void get_pen(void) {                     /* 32,6 Get Pen */
    libre();
    qd(6);
    plume_x = ControlPort.params[0] | ControlPort.params[1] << 8;
    plume_y = ControlPort.params[2] | ControlPort.params[3] << 8;
    plume_c = ControlPort.params[4];
}

int main(void) {
    putchar(12);
    init_graf();
    couleur(3);
    qd_xy(5, 10, 50);
    qd_xy(11, 70, 50);                          /* 32,11 : la plume finit au bout du trait */
    get_pen();                                  /* Get Pen */
    init_graf();
    printf("Plume : %d, %d, couleur %u\n", plume_x, plume_y, plume_c);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 70, 50, couleur 3
Mad Pascal
// Lire la position et la couleur de la plume (groupe 32, fonction 6, Trinity).
program qd6;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

var plume_x, plume_y: smallint;
    plume_c: byte;

procedure get_pen;                              // 32,6 Get Pen
begin
  NeoWaitMessage;
  qd(6);
  plume_x := smallint(wordParams[0]);
  plume_y := smallint(wordParams[1]);
  plume_c := NeoMessage.params[4];
end;

begin
  write(chr(12));
  init_graf;
  couleur(3);
  qd_xy(5, 10, 50);
  qd_xy(11, 70, 50);                            // 32,11 : la plume finit au bout du trait
  get_pen;                                      // Get Pen
  init_graf;
  writeln('Plume : ', plume_x, ', ', plume_y, ', couleur ', plume_c);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 70, 50, couleur 3
NeoBASIC
10 ' Lire la position et la couleur de la plume (groupe 32, fonction 6, Trinity)
20 cls : gosub 9400
30 c = 3 : gosub 9300
40 x = 10 : y = 50 : f = 5 : gosub 9200
50 x = 70 : y = 50 : f = 11 : gosub 9200 : ' 32,11 : la plume finit au bout du trait
60 gosub 9500 : ' Get Pen
70 gosub 9400
80 print "Plume : ";px;", ";py;", couleur ";pc
90 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
9500 ' 32,6 Get Pen : px, py, pc
9510 while peek($ff00) : wend : f = 6 : gosub 9110
9520 px = deek($ff04) : py = deek($ff06) : pc = peek($ff08)
9530 if px > 32767 then px = px - 65536
9540 if py > 32767 then py = py - 65536
9550 return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 70, 50, couleur 3
65C02 assembly (64tass)
; Lire la position et la couleur de la plume (groupe 32, fonction 6, 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 #12                    ; écran effacé : on relit des pixels
        jsr WriteCharacter
        lda #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #<b3
        ldx #>b3
        jsr envoi
        lda #<b4
        ldx #>b4
        jsr envoi
        ldx #4
_cp:    lda ControlPort+4,x
        sta pen,x
        dex
        bpl _cp
        lda #<b5
        ldx #>b5
        jsr envoi
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda pen
        ldx pen+1
        jsr dec16
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda pen+2
        ldx pen+2+1
        jsr dec16
        lda #<t8
        ldx #>t8
        jsr ecrire
        lda pen+4
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

b0:     .byte 32, 1, 0             ; 32,1 : Init Graf
b1:     .byte 32, 4, 1, 3          ; 32,4 : Set Pen Colour
b2:     .byte 32, 5, 4             ; 32,5 : Move To
        .word 10, 50
b3:     .byte 32, 11, 4            ; 32,11 : la plume finit au bout du trait
        .word 70, 50
b4:     .byte 32, 6, 0             ; Get Pen
pen:    .fill 5                    ; x, y (16 bits), couleur
b5:     .byte 32, 1, 0             ; 32,1 : Init Graf
t6:     .text "Plume : ", 0
t7:     .text ", ", 0
t8:     .text ", couleur ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 70, 50, couleur 3

32,7 Frame Rect Trinity

Draws the one-pixel outline of a rectangle in the pen colour.

Inputs
BytesTypeMeaning
P0-P1addraddress of the Rect

Outputs: none.

The outline is inside the rectangle: for 100, 100, 120, 110, the corners are at (100, 100) and (119, 109), and pixel (120, 100) stays empty. The inside is not touched. NeoBASIC has no keyword for this call.

Firmware documentation text

Draws the one pixel outline of the Rect at Parameters:0,1 in the pen colour, inside the rectangle, clipped.

C (llvm-mos)
/* Tracer le contour d'un rectangle (groupe 32, fonction 7, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static Rect r = {100, 100, 120, 110};

int main(void) {
    putchar(12);
    init_graf();
    couleur(6);
    qd_rect(7, &r);                             /* Frame Rect */
    uint8_t a = px(100, 100), b = px(119, 109); /* coins : le contour est à l'intérieur */
    uint8_t c = px(120, 100), d = px(110, 105); /* juste à droite, et au milieu */
    init_graf();
    printf("Coins : %u %u, a droite : %u, au milieu : %u\n", a, b, c, d);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Coins : 6 6, a droite : 0, au milieu : 0
Mad Pascal
// Tracer le contour d'un rectangle (groupe 32, fonction 7, Trinity).
program qd7;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

var r: Rect;
    a, b, c, d: byte;
begin
  write(chr(12));
  r.g := 100; r.h := 100; r.d := 120; r.b := 110;
  init_graf;
  couleur(6);
  qd_rect(7, @r);                               // Frame Rect
  a := NeoGetPixel(100, 100);                   // coins : le contour est à l'intérieur
  b := NeoGetPixel(119, 109);
  c := NeoGetPixel(120, 100);                   // juste à droite, et au milieu
  d := NeoGetPixel(110, 105);
  init_graf;
  writeln('Coins : ', a, ' ', b, ', a droite : ', c, ', au milieu : ', d);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Coins : 6 6, a droite : 0, au milieu : 0
NeoBASIC
10 ' Tracer le contour d'un rectangle (groupe 32, fonction 7, Trinity)
20 cls : q = alloc(8) : g = 100 : h = 100 : d = 120 : b = 110 : gosub 8000
30 gosub 9400 : c = 6 : gosub 9300
40 a = q : f = 7 : gosub 9000 : ' Frame Rect
50 c1 = point(100, 100) : c2 = point(119, 109) : ' coins : le contour est a l'interieur
60 dr = point(120, 100) : mi = point(110, 105) : ' juste a droite, et au milieu
70 gosub 9400
80 print "Coins : ";c1;" ";c2;", a droite : ";dr;", au milieu : ";mi
90 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Coins : 6 6, a droite : 0, au milieu : 0
65C02 assembly (64tass)
; Tracer le contour d'un rectangle (groupe 32, fonction 7, 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 #12                    ; écran effacé : on relit des pixels
        jsr WriteCharacter
        lda #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #100
        ldy #100
        jsr pixel
        sta c1
        lda #119
        ldy #109
        jsr pixel
        sta c2
        lda #120
        ldy #100
        jsr pixel
        sta dr
        lda #110
        ldy #105
        jsr pixel
        sta mi
        lda #<b3
        ldx #>b3
        jsr envoi
        lda #<t4
        ldx #>t4
        jsr ecrire
        lda c1
        jsr decimal
        lda #<t5
        ldx #>t5
        jsr ecrire
        lda c2
        jsr decimal
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda dr
        jsr decimal
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda mi
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel:  pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0-P1 : X
        stz ControlPort+5
        sty ControlPort+6          ; P2-P3 : Y
        stz ControlPort+7
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

q:      .word 100, 100, 120, 110          ; gauche, haut, droite, bas (droite et bas exclus)
b0:     .byte 32, 1, 0             ; 32,1 : Init Graf
b1:     .byte 32, 4, 1, 6          ; 32,4 : Set Pen Colour
b2:     .byte 32, 7, 2             ; Frame Rect
        .word q
c1:     .byte 0
c2:     .byte 0
dr:     .byte 0
mi:     .byte 0
b3:     .byte 32, 1, 0             ; 32,1 : Init Graf
t4:     .text "Coins : ", 0
t5:     .text " ", 0
t6:     .text ", a droite : ", 0
t7:     .text ", au milieu : ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Coins : 6 6, a droite : 0, au milieu : 0

32,8 Paint Rect Trinity

Paints a rectangle in the pen colour.

Inputs
BytesTypeMeaning
P0-P1addraddress of the Rect

Outputs: none.

The right and bottom edges are excluded: 100, 100, 104, 102 paints x 100 to 103 on lines 100 and 101. The pattern of 32,12 is not used (32,13 uses it). NeoBASIC has no keyword for this call.

Firmware documentation text

Fills the Rect at Parameters:0,1 with the pen colour, clipped.

C (llvm-mos)
/* Peindre un rectangle (groupe 32, fonction 8, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static Rect r = {100, 100, 104, 102};

int main(void) {
    putchar(12);
    init_graf();
    couleur(5);
    qd_rect(8, &r);                             /* Paint Rect : x 100 à 103, y 100 et 101 */
    uint8_t a = px(100, 100), b = px(103, 101), c = px(104, 101), d = px(103, 102);
    init_graf();
    printf("Dedans : %u %u, droite : %u, bas : %u\n", a, b, c, d);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Dedans : 5 5, droite : 0, bas : 0
Mad Pascal
// Peindre un rectangle (groupe 32, fonction 8, Trinity).
program qd8;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

var r: Rect;
    a, b, c, d: byte;
begin
  write(chr(12));
  r.g := 100; r.h := 100; r.d := 104; r.b := 102;
  init_graf;
  couleur(5);
  qd_rect(8, @r);                               // Paint Rect : x 100 à 103, y 100 et 101
  a := NeoGetPixel(100, 100);
  b := NeoGetPixel(103, 101);
  c := NeoGetPixel(104, 101);
  d := NeoGetPixel(103, 102);
  init_graf;
  writeln('Dedans : ', a, ' ', b, ', droite : ', c, ', bas : ', d);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Dedans : 5 5, droite : 0, bas : 0
NeoBASIC
10 ' Peindre un rectangle (groupe 32, fonction 8, Trinity)
20 cls : q = alloc(8) : g = 100 : h = 100 : d = 104 : b = 102 : gosub 8000
30 gosub 9400 : c = 5 : gosub 9300
40 a = q : f = 8 : gosub 9000 : ' Paint Rect : x 100 a 103, y 100 et 101
50 p1 = point(100, 100) : p2 = point(103, 101) : p3 = point(104, 101) : p4 = point(103, 102)
60 gosub 9400
70 print "Dedans : ";p1;" ";p2;", droite : ";p3;", bas : ";p4
80 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Dedans : 5 5, droite : 0, bas : 0
65C02 assembly (64tass)
; Peindre un rectangle (groupe 32, fonction 8, 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 #12                    ; écran effacé : on relit des pixels
        jsr WriteCharacter
        lda #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #100
        ldy #100
        jsr pixel
        sta p1
        lda #103
        ldy #101
        jsr pixel
        sta p2
        lda #104
        ldy #101
        jsr pixel
        sta p3
        lda #103
        ldy #102
        jsr pixel
        sta p4
        lda #<b3
        ldx #>b3
        jsr envoi
        lda #<t4
        ldx #>t4
        jsr ecrire
        lda p1
        jsr decimal
        lda #<t5
        ldx #>t5
        jsr ecrire
        lda p2
        jsr decimal
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda p3
        jsr decimal
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda p4
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel:  pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0-P1 : X
        stz ControlPort+5
        sty ControlPort+6          ; P2-P3 : Y
        stz ControlPort+7
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

q:      .word 100, 100, 104, 102          ; gauche, haut, droite, bas (droite et bas exclus)
b0:     .byte 32, 1, 0             ; 32,1 : Init Graf
b1:     .byte 32, 4, 1, 5          ; 32,4 : Set Pen Colour
b2:     .byte 32, 8, 2             ; Paint Rect : x 100 à 103, y 100 et 101
        .word q
p1:     .byte 0
p2:     .byte 0
p3:     .byte 0
p4:     .byte 0
b3:     .byte 32, 1, 0             ; 32,1 : Init Graf
t4:     .text "Dedans : ", 0
t5:     .text " ", 0
t6:     .text ", droite : ", 0
t7:     .text ", bas : ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Dedans : 5 5, droite : 0, bas : 0

32,9 Erase Rect Trinity

Fills a rectangle with a given background colour.

Inputs
BytesTypeMeaning
P0-P1addraddress of the Rect
P2uint8background colour

Outputs: none.

The pen colour is not changed. The example paints a square in colour 4, then erases its centre in colour 2. NeoBASIC has no keyword for this call.

Firmware documentation text

Fills the Rect at Parameters:0,1 with the colour in Parameter:2 (the background), clipped.

C (llvm-mos)
/* Effacer un rectangle avec une couleur de fond (groupe 32, fonction 9, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static Rect r = {100, 100, 110, 110}, petit = {102, 102, 106, 106};

int main(void) {
    putchar(12);
    init_graf();
    couleur(4);
    qd_rect(8, &r);                             /* 32,8 : un carré de couleur 4 */
    libre();
    ControlPort.params[0] = (uint16_t)&petit & 0xFF;
    ControlPort.params[1] = (uint16_t)&petit >> 8;
    ControlPort.params[2] = 2;                  /* P2 : couleur du fond */
    qd(9);                                      /* Erase Rect */
    uint8_t a = px(103, 103), b = px(100, 100);
    init_graf();
    printf("Efface : %u, autour : %u\n", a, b);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Efface : 2, autour : 4
Mad Pascal
// Effacer un rectangle avec une couleur de fond (groupe 32, fonction 9, Trinity).
program qd9;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

var r, petit: Rect;
    a, b: byte;
begin
  write(chr(12));
  r.g := 100; r.h := 100; r.d := 110; r.b := 110;
  petit.g := 102; petit.h := 102; petit.d := 106; petit.b := 106;
  init_graf;
  couleur(4);
  qd_rect(8, @r);                               // 32,8 : un carré de couleur 4
  NeoWaitMessage;
  wordParams[0] := word(@petit);
  NeoMessage.params[2] := 2;                    // P2 : couleur du fond
  qd(9);                                        // Erase Rect
  a := NeoGetPixel(103, 103);
  b := NeoGetPixel(100, 100);
  init_graf;
  writeln('Efface : ', a, ', autour : ', b);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Efface : 2, autour : 4
NeoBASIC
10 ' Effacer un rectangle avec une couleur de fond (groupe 32, fonction 9, Trinity)
20 cls : r = alloc(8) : q = r : g = 100 : h = 100 : d = 110 : b = 110 : gosub 8000
30 pe = alloc(8) : q = pe : g = 102 : h = 102 : d = 106 : b = 106 : gosub 8000
40 gosub 9400 : c = 4 : gosub 9300
50 a = r : f = 8 : gosub 9000 : ' 32,8 : un carre de couleur 4
60 while peek($ff00) : wend : doke $ff04, pe : poke $ff06, 2 : f = 9 : gosub 9110 : ' Erase Rect, P2 : couleur du fond
70 p1 = point(103, 103) : p2 = point(100, 100)
80 gosub 9400
90 print "Efface : ";p1;", autour : ";p2
100 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Efface : 2, autour : 4
65C02 assembly (64tass)
; Effacer un rectangle avec une couleur de fond (groupe 32, 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 #12                    ; écran effacé : on relit des pixels
        jsr WriteCharacter
        lda #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #<b3
        ldx #>b3
        jsr envoi
        lda #103
        ldy #103
        jsr pixel
        sta p1
        lda #100
        ldy #100
        jsr pixel
        sta p2
        lda #<b4
        ldx #>b4
        jsr envoi
        lda #<t5
        ldx #>t5
        jsr ecrire
        lda p1
        jsr decimal
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda p2
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel:  pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0-P1 : X
        stz ControlPort+5
        sty ControlPort+6          ; P2-P3 : Y
        stz ControlPort+7
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

r:      .word 100, 100, 110, 110          ; gauche, haut, droite, bas (droite et bas exclus)
pe:     .word 102, 102, 106, 106          ; gauche, haut, droite, bas (droite et bas exclus)
b0:     .byte 32, 1, 0             ; 32,1 : Init Graf
b1:     .byte 32, 4, 1, 4          ; 32,4 : Set Pen Colour
b2:     .byte 32, 8, 2             ; 32,8 : un carré de couleur 4
        .word r
b3:     .byte 32, 9, 3             ; Erase Rect, P2 : couleur du fond
        .word pe
        .byte 2
p1:     .byte 0
p2:     .byte 0
b4:     .byte 32, 1, 0             ; 32,1 : Init Graf
t5:     .text "Efface : ", 0
t6:     .text ", autour : ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Efface : 2, autour : 4

32,10 Invert Rect Trinity

Inverts the pixels of a rectangle.

Inputs
BytesTypeMeaning
P0-P1addraddress of the Rect

Outputs: none.

In mode 0, each colour index is exclusive-ORed with $FF: 5 becomes 250. A second inversion gives back the starting image. Depending on the mode, Trinity uses $0F or 1 instead of $FF. NeoBASIC has no keyword for this call.

Firmware documentation text

Inverts every pixel of the Rect at Parameters:0,1 (colour index XOR $FF, $0F or 1 depending on the mode), clipped.

C (llvm-mos)
/* Inverser les pixels d'un rectangle (groupe 32, fonction 10, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static Rect r = {100, 100, 104, 104};

int main(void) {
    putchar(12);
    init_graf();
    couleur(5);
    qd_rect(8, &r);
    qd_rect(10, &r);                            /* Invert Rect : en mode 0, XOR $FF */
    uint8_t a = px(101, 101);
    qd_rect(10, &r);                            /* deux fois : retour au départ */
    uint8_t b = px(101, 101);
    init_graf();
    printf("Inverse : %u, deux fois : %u\n", a, b);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Inverse : 250, deux fois : 5
Mad Pascal
// Inverser les pixels d'un rectangle (groupe 32, fonction 10, Trinity).
program qd10;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

var r: Rect;
    a, b: byte;
begin
  write(chr(12));
  r.g := 100; r.h := 100; r.d := 104; r.b := 104;
  init_graf;
  couleur(5);
  qd_rect(8, @r);
  qd_rect(10, @r);                              // Invert Rect : en mode 0, XOR $FF
  a := NeoGetPixel(101, 101);
  qd_rect(10, @r);                              // deux fois : retour au départ
  b := NeoGetPixel(101, 101);
  init_graf;
  writeln('Inverse : ', a, ', deux fois : ', b);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Inverse : 250, deux fois : 5
NeoBASIC
10 ' Inverser les pixels d'un rectangle (groupe 32, fonction 10, Trinity)
20 cls : q = alloc(8) : g = 100 : h = 100 : d = 104 : b = 104 : gosub 8000
30 gosub 9400 : c = 5 : gosub 9300
40 a = q : f = 8 : gosub 9000
50 f = 10 : gosub 9000 : p1 = point(101, 101) : ' Invert Rect : en mode 0, XOR $FF
60 f = 10 : gosub 9000 : p2 = point(101, 101) : ' deux fois : retour au depart
70 gosub 9400
80 print "Inverse : ";p1;", deux fois : ";p2
90 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Inverse : 250, deux fois : 5
65C02 assembly (64tass)
; Inverser les pixels d'un rectangle (groupe 32, 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:  lda #12                    ; écran effacé : on relit des pixels
        jsr WriteCharacter
        lda #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #<b3
        ldx #>b3
        jsr envoi
        lda #101
        ldy #101
        jsr pixel
        sta p1
        lda #<b4
        ldx #>b4
        jsr envoi
        lda #101
        ldy #101
        jsr pixel
        sta p2
        lda #<b5
        ldx #>b5
        jsr envoi
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda p1
        jsr decimal
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda p2
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel:  pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0-P1 : X
        stz ControlPort+5
        sty ControlPort+6          ; P2-P3 : Y
        stz ControlPort+7
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

q:      .word 100, 100, 104, 104          ; gauche, haut, droite, bas (droite et bas exclus)
b0:     .byte 32, 1, 0             ; 32,1 : Init Graf
b1:     .byte 32, 4, 1, 5          ; 32,4 : Set Pen Colour
b2:     .byte 32, 8, 2             ; 32,8
        .word q
b3:     .byte 32, 10, 2            ; Invert Rect : en mode 0, XOR $FF
        .word q
p1:     .byte 0
b4:     .byte 32, 10, 2            ; deux fois : retour au départ
        .word q
p2:     .byte 0
b5:     .byte 32, 1, 0             ; 32,1 : Init Graf
t6:     .text "Inverse : ", 0
t7:     .text ", deux fois : ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Inverse : 250, deux fois : 5

32,11 Line To Trinity

Draws a line from the pen to the given point, in the pen colour, and moves the pen there.

Inputs
BytesTypeMeaning
P0-P1int16end X (signed)
P2-P3int16end Y (signed)

Outputs: none.

Both the start point and the end point are drawn, but not the next pixel. NeoBASIC has no keyword for this call.

Firmware documentation text

Draws a line from the pen to Parameters:0,1 (X) and Parameters:2,3 (Y) in the pen colour, clipped, and moves the pen there.

C (llvm-mos)
/* Tracer un trait depuis la plume (groupe 32, fonction 11, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

int main(void) {
    putchar(12);
    init_graf();
    couleur(7);
    qd_xy(5, 50, 60);                           /* 32,5 : départ */
    qd_xy(11, 60, 60);                          /* Line To : le point d'arrivée est tracé */
    uint8_t a = px(50, 60), b = px(60, 60), c = px(61, 60);
    init_graf();
    printf("Depart : %u, arrivee : %u, apres : %u\n", a, b, c);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Depart : 7, arrivee : 7, apres : 0
Mad Pascal
// Tracer un trait depuis la plume (groupe 32, fonction 11, Trinity).
program qd11;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

var a, b, c: byte;
begin
  write(chr(12));
  init_graf;
  couleur(7);
  qd_xy(5, 50, 60);                             // 32,5 : départ
  qd_xy(11, 60, 60);                            // Line To : le point d'arrivée est tracé
  a := NeoGetPixel(50, 60);
  b := NeoGetPixel(60, 60);
  c := NeoGetPixel(61, 60);
  init_graf;
  writeln('Depart : ', a, ', arrivee : ', b, ', apres : ', c);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Depart : 7, arrivee : 7, apres : 0
NeoBASIC
10 ' Tracer un trait depuis la plume (groupe 32, fonction 11, Trinity)
20 cls : gosub 9400 : c = 7 : gosub 9300
30 x = 50 : y = 60 : f = 5 : gosub 9200 : ' 32,5 : depart
40 x = 60 : y = 60 : f = 11 : gosub 9200 : ' Line To : le point d'arrivee est trace
50 p1 = point(50, 60) : p2 = point(60, 60) : p3 = point(61, 60)
60 gosub 9400
70 print "Depart : ";p1;", arrivee : ";p2;", apres : ";p3
80 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Depart : 7, arrivee : 7, apres : 0
65C02 assembly (64tass)
; Tracer un trait depuis la plume (groupe 32, 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 #12                    ; écran effacé : on relit des pixels
        jsr WriteCharacter
        lda #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #<b3
        ldx #>b3
        jsr envoi
        lda #50
        ldy #60
        jsr pixel
        sta p1
        lda #60
        ldy #60
        jsr pixel
        sta p2
        lda #61
        ldy #60
        jsr pixel
        sta p3
        lda #<b4
        ldx #>b4
        jsr envoi
        lda #<t5
        ldx #>t5
        jsr ecrire
        lda p1
        jsr decimal
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda p2
        jsr decimal
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda p3
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel:  pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0-P1 : X
        stz ControlPort+5
        sty ControlPort+6          ; P2-P3 : Y
        stz ControlPort+7
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

b0:     .byte 32, 1, 0             ; 32,1 : Init Graf
b1:     .byte 32, 4, 1, 7          ; 32,4 : Set Pen Colour
b2:     .byte 32, 5, 4             ; 32,5 : Move To
        .word 50, 60
b3:     .byte 32, 11, 4            ; Line To : le point d'arrivée est tracé
        .word 60, 60
p1:     .byte 0
p2:     .byte 0
p3:     .byte 0
b4:     .byte 32, 1, 0             ; 32,1 : Init Graf
t5:     .text "Depart : ", 0
t6:     .text ", arrivee : ", 0
t7:     .text ", apres : ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Depart : 7, arrivee : 7, apres : 0

32,12 Set Pattern Trinity

Loads the 8 × 8 pattern used by 32,13.

Inputs
BytesTypeMeaning
P0-P1addraddress of the 8 pattern bytes: one byte per row, bit 7 = left pixel

Outputs: none.

The pattern is aligned on screen coordinates, not on the rectangle: the example fills from x = 96, a multiple of 8, so that the first column gets bit 7. 32,1 restores the solid pattern. The example loads a checkerboard ($AA, $55): set bits in colour 3, clear bits in colour 9. NeoBASIC has no keyword for this call.

Firmware documentation text

Loads the 8x8 fill pattern from the 8 bytes at Parameters:0,1 (one byte per row, bit 7 = left pixel). Init Graf resets it to solid. The pattern is aligned on screen coordinates.

C (llvm-mos)
/* Choisir le motif de remplissage (groupe 32, fonction 12, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static const uint8_t damier[8] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
static void motif(const uint8_t *m) {           /* 32,12 Set Pattern : 8 octets, bit 7 = pixel de gauche */
    libre();
    ControlPort.params[0] = (uint16_t)m & 0xFF;
    ControlPort.params[1] = (uint16_t)m >> 8;
    qd(12);
}
static void remplir(Rect *r, uint8_t fond) {    /* 32,13 Fill Rect : bits à 1 couleur de la plume, à 0 fond */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    ControlPort.params[2] = fond;
    qd(13);
}

static Rect r = {96, 100, 104, 102};            /* x 96 à 103 : une rangée du motif, alignée sur l'écran */

int main(void) {
    putchar(12);
    init_graf();
    couleur(3);
    motif(damier);                              /* Set Pattern */
    remplir(&r, 9);
    uint8_t l[2][8];
    for (uint8_t y = 0; y < 2; y++)
        for (uint8_t x = 0; x < 8; x++)
            l[y][x] = px(96 + x, 100 + y);
    init_graf();                                /* remet aussi le motif plein */
    for (uint8_t y = 0; y < 2; y++) {
        printf("y %u :", 100 + y);
        for (uint8_t x = 0; x < 8; x++)
            printf(" %u", l[y][x]);
        printf("\n");
    }
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
y 100 : 3 9 3 9 3 9 3 9
y 101 : 9 3 9 3 9 3 9 3
Mad Pascal
// Choisir le motif de remplissage (groupe 32, fonction 12, Trinity).
program qd12;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

const damier: array[0..7] of byte = ($AA, $55, $AA, $55, $AA, $55, $AA, $55);
procedure motif(m: pointer);                    // 32,12 Set Pattern : 8 octets, bit 7 = pixel de gauche
begin
  qd_rect(12, m);
end;
procedure remplir(r: pointer; fond: byte);      // 32,13 Fill Rect : bits à 1 couleur de la plume, à 0 fond
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  NeoMessage.params[2] := fond;
  qd(13);
end;

var r: Rect;
    l: array[0..15] of byte;
    x, y: byte;
begin
  write(chr(12));
  r.g := 96; r.h := 100; r.d := 104; r.b := 102;   // x 96 à 103 : une rangée du motif, alignée sur l'écran
  init_graf;
  couleur(3);
  motif(@damier);                               // Set Pattern
  remplir(@r, 9);
  for y := 0 to 1 do
    for x := 0 to 7 do l[y * 8 + x] := NeoGetPixel(96 + x, 100 + y);
  init_graf;                                    // remet aussi le motif plein
  for y := 0 to 1 do begin
    write('y ', 100 + y, ' :');
    for x := 0 to 7 do write(' ', l[y * 8 + x]);
    writeln;
  end;
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
y 100 : 3 9 3 9 3 9 3 9
y 101 : 9 3 9 3 9 3 9 3
NeoBASIC
10 ' Choisir le motif de remplissage (groupe 32, fonction 12, Trinity)
20 cls : q = alloc(8) : g = 96 : h = 100 : d = 104 : b = 102 : gosub 8000 : ' x 96 a 103 : une rangee du motif, alignee sur l'ecran
30 m = alloc(8) : for i = 0 to 3 : poke m + i * 2, $aa : poke m + i * 2 + 1, $55 : next i : ' damier, bit 7 = pixel de gauche
40 gosub 9400 : c = 3 : gosub 9300
50 a = m : f = 12 : gosub 9000 : ' Set Pattern
60 while peek($ff00) : wend : doke $ff04, q : poke $ff06, 9 : f = 13 : gosub 9110 : ' 32,13 : bits a 0 en couleur 9
70 l0$ = "" : l1$ = "" : for x = 96 to 103 : l0$ = l0$ + " " + str$(point(x, 100)) : l1$ = l1$ + " " + str$(point(x, 101)) : next x
80 gosub 9400 : ' remet aussi le motif plein
90 print "y 100 :";l0$
100 print "y 101 :";l1$
110 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
y 100 : 3 9 3 9 3 9 3 9
y 101 : 9 3 9 3 9 3 9 3
65C02 assembly (64tass)
; Choisir le motif de remplissage (groupe 32, 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 #12                    ; écran effacé : on relit des pixels
        jsr WriteCharacter
        lda #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #<b3
        ldx #>b3
        jsr envoi
        ldx #0
_l4:   phx
        txa
        clc
        adc #96
        ldy #100
        jsr pixel
        plx
        sta l0,x
        inx
        cpx #8
        bne _l4
        ldx #0
_l5:   phx
        txa
        clc
        adc #96
        ldy #101
        jsr pixel
        plx
        sta l1,x
        inx
        cpx #8
        bne _l5
        lda #<b6
        ldx #>b6
        jsr envoi
        lda #<t7
        ldx #>t7
        jsr ecrire
        ldx #0
_a8:   lda #' '
        jsr WriteCharacter
        lda l0,x
        jsr decimal
        inx
        cpx #8
        bne _a8
        lda #13
        jsr WriteCharacter
        lda #<t9
        ldx #>t9
        jsr ecrire
        ldx #0
_a10:   lda #' '
        jsr WriteCharacter
        lda l1,x
        jsr decimal
        inx
        cpx #8
        bne _a10
        lda #13
        jsr WriteCharacter
        rts

; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel:  pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0-P1 : X
        stz ControlPort+5
        sty ControlPort+6          ; P2-P3 : Y
        stz ControlPort+7
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

q:      .word 96, 100, 104, 102          ; gauche, haut, droite, bas (droite et bas exclus)
motif:  .byte $AA, $55, $AA, $55, $AA, $55, $AA, $55   ; damier, bit 7 = pixel de gauche
b0:     .byte 32, 1, 0             ; 32,1 : Init Graf
b1:     .byte 32, 4, 1, 3          ; 32,4 : Set Pen Colour
b2:     .byte 32, 12, 2            ; Set Pattern
        .word motif
b3:     .byte 32, 13, 3            ; 32,13 : bits à 0 en couleur 9
        .word q
        .byte 9
l0:     .fill 8
l1:     .fill 8
b6:     .byte 32, 1, 0             ; remet aussi le motif plein
t7:     .text "y 100 :", 0
t9:     .text "y 101 :", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
y 100 : 3 9 3 9 3 9 3 9
y 101 : 9 3 9 3 9 3 9 3

32,13 Fill Rect Trinity

Fills a rectangle with the pattern: set bits in the pen colour, clear bits in the given colour.

Inputs
BytesTypeMeaning
P0-P1addraddress of the Rect
P2uint8colour of clear bits

Outputs: none.

With the solid starting pattern, 32,13 does the same as 32,8. The example then fills with stripes ($F0: four pixels on, four off). NeoBASIC has no keyword for this call.

Firmware documentation text

Fills the Rect at Parameters:0,1 with the pattern : set bits in the pen colour, clear bits in the colour of Parameter:2. Clipped.

C (llvm-mos)
/* Remplir un rectangle avec le motif (groupe 32, fonction 13, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static const uint8_t damier[8] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
static void motif(const uint8_t *m) {           /* 32,12 Set Pattern : 8 octets, bit 7 = pixel de gauche */
    libre();
    ControlPort.params[0] = (uint16_t)m & 0xFF;
    ControlPort.params[1] = (uint16_t)m >> 8;
    qd(12);
}
static void remplir(Rect *r, uint8_t fond) {    /* 32,13 Fill Rect : bits à 1 couleur de la plume, à 0 fond */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    ControlPort.params[2] = fond;
    qd(13);
}

static const uint8_t rayures[8] = {0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0};   /* 4 pixels allumés, 4 éteints */
static Rect r = {96, 100, 104, 101};

int main(void) {
    putchar(12);
    init_graf();
    uint8_t avant[2] = {px(96, 100), px(103, 100)};
    couleur(3);
    remplir(&r, 9);                             /* Fill Rect, motif plein au départ */
    uint8_t plein[2] = {px(96, 100), px(103, 100)};
    motif(rayures);
    remplir(&r, 9);                             /* Fill Rect : 3 pour les bits à 1, 9 pour les bits à 0 */
    uint8_t ray[2] = {px(96, 100), px(103, 100)};
    init_graf();
    printf("Avant : %u %u, motif plein : %u %u, rayures : %u %u\n", avant[0], avant[1], plein[0], plein[1], ray[0], ray[1]);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Avant : 0 0, motif plein : 3 3, rayures : 3 9
Mad Pascal
// Remplir un rectangle avec le motif (groupe 32, fonction 13, Trinity).
program qd13;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

const damier: array[0..7] of byte = ($AA, $55, $AA, $55, $AA, $55, $AA, $55);
procedure motif(m: pointer);                    // 32,12 Set Pattern : 8 octets, bit 7 = pixel de gauche
begin
  qd_rect(12, m);
end;
procedure remplir(r: pointer; fond: byte);      // 32,13 Fill Rect : bits à 1 couleur de la plume, à 0 fond
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  NeoMessage.params[2] := fond;
  qd(13);
end;

const rayures: array[0..7] of byte = ($F0, $F0, $F0, $F0, $F0, $F0, $F0, $F0);   // 4 pixels allumés, 4 éteints
var r: Rect;
    a0, a1, p0, p1, r0, r1: byte;
begin
  write(chr(12));
  r.g := 96; r.h := 100; r.d := 104; r.b := 101;
  init_graf;
  a0 := NeoGetPixel(96, 100); a1 := NeoGetPixel(103, 100);
  couleur(3);
  remplir(@r, 9);                               // Fill Rect, motif plein au départ
  p0 := NeoGetPixel(96, 100); p1 := NeoGetPixel(103, 100);
  motif(@rayures);
  remplir(@r, 9);                               // Fill Rect : 3 pour les bits à 1, 9 pour les bits à 0
  r0 := NeoGetPixel(96, 100); r1 := NeoGetPixel(103, 100);
  init_graf;
  writeln('Avant : ', a0, ' ', a1, ', motif plein : ', p0, ' ', p1, ', rayures : ', r0, ' ', r1);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Avant : 0 0, motif plein : 3 3, rayures : 3 9
NeoBASIC
10 ' Remplir un rectangle avec le motif (groupe 32, fonction 13, Trinity)
20 cls : q = alloc(8) : g = 96 : h = 100 : d = 104 : b = 101 : gosub 8000
30 m = alloc(8) : for i = 0 to 7 : poke m + i, $f0 : next i : ' rayures : 4 pixels allumes, 4 eteints
40 gosub 9400 : a0 = point(96, 100) : a1 = point(103, 100)
50 c = 3 : gosub 9300
60 gosub 2000 : p0 = point(96, 100) : p1 = point(103, 100) : ' Fill Rect, motif plein au depart
70 a = m : f = 12 : gosub 9000
80 gosub 2000 : r0 = point(96, 100) : r1 = point(103, 100) : ' 3 pour les bits a 1, 9 pour les bits a 0
90 gosub 9400
100 print "Avant : ";a0;" ";a1;", motif plein : ";p0;" ";p1;", rayures : ";r0;" ";r1
110 end
2000 ' Fill Rect sur q, fond 9
2010 while peek($ff00) : wend : doke $ff04, q : poke $ff06, 9 : f = 13 : gosub 9110
2020 return
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Avant : 0 0, motif plein : 3 3, rayures : 3 9
65C02 assembly (64tass)
; Remplir un rectangle avec le motif (groupe 32, fonction 13, 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 #12                    ; écran effacé : on relit des pixels
        jsr WriteCharacter
        lda #<b0
        ldx #>b0
        jsr envoi
        lda #96
        ldy #100
        jsr pixel
        sta a0
        lda #103
        ldy #100
        jsr pixel
        sta a1
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #96
        ldy #100
        jsr pixel
        sta p0
        lda #103
        ldy #100
        jsr pixel
        sta p1
        lda #<b3
        ldx #>b3
        jsr envoi
        lda #<b4
        ldx #>b4
        jsr envoi
        lda #96
        ldy #100
        jsr pixel
        sta r0
        lda #103
        ldy #100
        jsr pixel
        sta r1
        lda #<b5
        ldx #>b5
        jsr envoi
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda a0
        jsr decimal
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda a1
        jsr decimal
        lda #<t8
        ldx #>t8
        jsr ecrire
        lda p0
        jsr decimal
        lda #<t9
        ldx #>t9
        jsr ecrire
        lda p1
        jsr decimal
        lda #<t10
        ldx #>t10
        jsr ecrire
        lda r0
        jsr decimal
        lda #<t11
        ldx #>t11
        jsr ecrire
        lda r1
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel:  pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0-P1 : X
        stz ControlPort+5
        sty ControlPort+6          ; P2-P3 : Y
        stz ControlPort+7
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

q:      .word 96, 100, 104, 101          ; gauche, haut, droite, bas (droite et bas exclus)
motif:  .fill 8, $F0                ; rayures : 4 pixels allumés, 4 éteints
b0:     .byte 32, 1, 0             ; 32,1 : Init Graf
a0:     .byte 0
a1:     .byte 0
b1:     .byte 32, 4, 1, 3          ; 32,4 : Set Pen Colour
b2:     .byte 32, 13, 3            ; Fill Rect, motif plein au départ, fond 9
        .word q
        .byte 9
p0:     .byte 0
p1:     .byte 0
b3:     .byte 32, 12, 2            ; 32,12
        .word motif
b4:     .byte 32, 13, 3            ; 3 pour les bits à 1, 9 pour les bits à 0
        .word q
        .byte 9
r0:     .byte 0
r1:     .byte 0
b5:     .byte 32, 1, 0             ; 32,1 : Init Graf
t6:     .text "Avant : ", 0
t7:     .text " ", 0
t8:     .text ", motif plein : ", 0
t9:     .text " ", 0
t10:    .text ", rayures : ", 0
t11:    .text " ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Avant : 0 0, motif plein : 3 3, rayures : 3 9

32,14 Copy Bits Trinity

Draws a source area (described as for 12,3) on the draw page, clipped by the rectangle of 32,2.

Inputs
BytesTypeMeaning
P0uint8action: 0 copy, 1 masked, 2 solid colour
P1-P2addraddress of the 12-byte source descriptor
P3-P4int16X (signed)
P5-P6int16Y (signed)

Outputs: none.

All source formats of 12,3 are accepted. The example draws 8 pixels of 4 bits (1 to 8) at (100, 120) under a clip that stops before x = 104: only the first four show. As for 12,4, a clipped left edge is rounded up to a whole source byte. Outside mode 0, the copy is done pixel by pixel. NeoBASIC has no keyword for this call.

Firmware documentation text

Blits the source area described at Parameters:1,2 (the 12 byte structure of Function 12,3, any source format) at Parameters:3,4 (X) and Parameters:5,6 (Y) of the draw page, with the blit action of Parameter:0 (0 copy, 1 masked, 2 solid), clipped to the clip rectangle. As Function 12,4, the left clip is rounded up to a whole source byte. Outside mode 0 the copy is done pixel by pixel (source values are reduced to their bit 0 in monochrome).

C (llvm-mos)
/* Copier une image dans la zone de dessin, découpée (groupe 32, fonction 14, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static uint8_t pixels[4] = {0x12, 0x34, 0x56, 0x78};   /* 8 pixels de 4 bits : 1 à 8 */
static uint8_t source[12];                      /* descripteur de zone de 12,3 */
static Rect zone = {0, 0, 104, 240};            /* découpe : rien au-delà de x = 103 */

int main(void) {
    putchar(12);
    init_graf();
    source[0] = (uint16_t)pixels & 0xFF;        /* adresse en RAM du 6502 (page $00) */
    source[1] = (uint16_t)pixels >> 8;
    source[6] = 1;                              /* format 1 : paires de 4 bits */
    source[9] = 1;                              /* hauteur */
    source[10] = 8;                             /* largeur */
    qd_rect(2, &zone);                          /* 32,2 */
    libre();
    ControlPort.params[0] = 0;                  /* P0 : action 0, copie */
    ControlPort.params[1] = (uint16_t)source & 0xFF;   /* P1-P2 : zone source */
    ControlPort.params[2] = (uint16_t)source >> 8;
    ControlPort.params[3] = 100;                /* P3-P4 : X */
    ControlPort.params[4] = 0;
    ControlPort.params[5] = 120;                /* P5-P6 : Y */
    ControlPort.params[6] = 0;
    uint8_t e = qd(14);                         /* Copy Bits */
    uint8_t l[8];
    for (uint8_t x = 0; x < 8; x++)
        l[x] = px(100 + x, 120);
    init_graf();
    printf("Erreur %u ; x 100 a 107 :", e);
    for (uint8_t x = 0; x < 8; x++)
        printf(" %u", l[x]);
    printf("\n");
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Erreur 0 ; x 100 a 107 : 1 2 3 4 0 0 0 0
Mad Pascal
// Copier une image dans la zone de dessin, découpée (groupe 32, fonction 14, Trinity).
program qd14;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

const pixels: array[0..3] of byte = ($12, $34, $56, $78);   // 8 pixels de 4 bits : 1 à 8
var source: array[0..11] of byte;               // descripteur de zone de 12,3
    zone: Rect;
    l: array[0..7] of byte;
    x, e: byte;
begin
  write(chr(12));
  init_graf;
  fillchar(@source, 12, 0);
  source[0] := lo(word(@pixels));               // adresse en RAM du 6502 (page $00)
  source[1] := hi(word(@pixels));
  source[6] := 1;                               // format 1 : paires de 4 bits
  source[9] := 1;                               // hauteur
  source[10] := 8;                              // largeur
  zone.g := 0; zone.h := 0; zone.d := 104; zone.b := 240;   // découpe : rien au-delà de x = 103
  qd_rect(2, @zone);
  NeoWaitMessage;
  NeoMessage.params[0] := 0;                    // P0 : action 0, copie
  wordxParams[0] := word(@source);              // P1-P2 : zone source
  wordxParams[1] := 100;                        // P3-P4 : X
  wordxParams[2] := 120;                        // P5-P6 : Y
  e := qd(14);                                  // Copy Bits
  for x := 0 to 7 do l[x] := NeoGetPixel(100 + x, 120);
  init_graf;
  write('Erreur ', e, ' ; x 100 a 107 :');
  for x := 0 to 7 do write(' ', l[x]);
  writeln;
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Erreur 0 ; x 100 a 107 : 1 2 3 4 0 0 0 0
NeoBASIC
10 ' Copier une image dans la zone de dessin, decoupee (groupe 32, fonction 14, Trinity)
20 cls : gosub 9400
30 pp = alloc(4) : poke pp, $12 : poke pp + 1, $34 : poke pp + 2, $56 : poke pp + 3, $78 : ' 8 pixels de 4 bits : 1 a 8
40 s = alloc(12) : for i = 0 to 11 : poke s + i, 0 : next i
50 doke s, pp : poke s + 6, 1 : poke s + 9, 1 : poke s + 10, 8 : ' descripteur de 12,3 : format 1, hauteur 1, largeur 8
60 q = alloc(8) : g = 0 : h = 0 : d = 104 : b = 240 : gosub 8000 : a = q : f = 2 : gosub 9000 : ' decoupe : rien au-dela de x = 103
70 while peek($ff00) : wend
80 poke $ff04, 0 : doke $ff05, s : doke $ff07, 100 : doke $ff09, 120 : f = 14 : gosub 9110 : ' Copy Bits : action 0, en (100, 120)
90 l$ = "" : for x = 100 to 107 : l$ = l$ + " " + str$(point(x, 120)) : next x
100 gosub 9400
110 print "Erreur ";e;" ; x 100 a 107 :";l$
120 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Erreur 0 ; x 100 a 107 : 1 2 3 4 0 0 0 0
65C02 assembly (64tass)
; Copier une image dans la zone de dessin, découpée (groupe 32, fonction 14, 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 #12                    ; écran effacé : on relit des pixels
        jsr WriteCharacter
        lda #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda ControlPort+2
        sta e
        ldx #0
_l3:   phx
        txa
        clc
        adc #100
        ldy #120
        jsr pixel
        plx
        sta l,x
        inx
        cpx #8
        bne _l3
        lda #<b4
        ldx #>b4
        jsr envoi
        lda #<t5
        ldx #>t5
        jsr ecrire
        lda e
        jsr decimal
        lda #<t6
        ldx #>t6
        jsr ecrire
        ldx #0
_a7:   lda #' '
        jsr WriteCharacter
        lda l,x
        jsr decimal
        inx
        cpx #8
        bne _a7
        lda #13
        jsr WriteCharacter
        rts

; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel:  pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0-P1 : X
        stz ControlPort+5
        sty ControlPort+6          ; P2-P3 : Y
        stz ControlPort+7
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

q:      .word 0, 0, 104, 240          ; gauche, haut, droite, bas (droite et bas exclus)
pixels: .byte $12, $34, $56, $78   ; 8 pixels de 4 bits : 1 à 8
source: .word pixels              ; descripteur de 12,3 : adresse en RAM du 6502...
        .byte 0, 0                 ; ... page $00, octet de bourrage
        .word 0                    ; pas
        .byte 1, 0, 0, 1           ; format 1 (paires de 4 bits), transparent, uni, hauteur 1
        .word 8                    ; largeur
b0:     .byte 32, 1, 0             ; 32,1 : Init Graf
b1:     .byte 32, 2, 2             ; découpe : rien au-delà de x = 103
        .word q
b2:     .byte 32, 14, 7, 0         ; Copy Bits : action 0, en (100, 120)
        .word source, 100, 120
e:      .byte 0
l:      .fill 8
b4:     .byte 32, 1, 0             ; 32,1 : Init Graf
t5:     .text "Erreur ", 0
t6:     .text " ; x 100 a 107 :", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Erreur 0 ; x 100 a 107 : 1 2 3 4 0 0 0 0

32,15 Set Font Trinity

Selects the proportional font used by 32,16 and 32,17.

Inputs
BytesTypeMeaning
P0uint8page: $00 6502 RAM, $90 graphics memory
P1-P2addrfont address (0 in page 0: built-in 6 × 8 font)
Outputs
BytesTypeMeaning
erreuruint81 if the header or the size is wrong

NF1 format: "NF", version 1, height, first character, character count, spacing, bytes per row (1 or 2), then for each character its width and one line per row, bit 7 = left pixel. The font is read in place at each call: it must stay in memory. The example builds a font with a single character, "A", drawn as an 8 × 8 frame, writes it with 32,16, then tries a wrong header before going back to the built-in font. NeoBASIC has no keyword for this call.

Firmware documentation text

Selects the proportional font at page Parameter:0, address Parameters:1,2 (pages of Function 12,2 : $00 6502 RAM, $90 graphics RAM ; load a font file there with Function 3,2 or 12,1). Page 0 address 0 restores the built in 6x8 font. The font is read in place at each call, without copy. NF1 format (made by tools/mkfont.py of the fork archive) : "NF", version 1, height, first character, character count, spacing, bytes per row (1 or 2), then one glyph per character of width byte plus height rows, bit 7 = left pixel. Error 1 if the header or the size is invalid.

C (llvm-mos)
/* Choisir une police proportionnelle (groupe 32, fonction 15, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

/* Une police NF1 d'un seul caractère, « A » : en-tête puis largeur et 8 rangées (bit 7 = pixel de gauche). */
static const uint8_t police[] = {'N', 'F', 1, 8, 'A', 1, 1, 1,   /* NF, version 1, hauteur 8, premier « A », 1 caractère, espacement 1, 1 octet par rangée */
                                 8, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF};   /* largeur 8 : un cadre */
static uint8_t choisir_police(uint8_t page, uint16_t adresse) {   /* 32,15 Set Font */
    libre();
    ControlPort.params[0] = page;               /* P0 : page ($00 RAM du 6502, $90 mémoire graphique) */
    ControlPort.params[1] = adresse & 0xFF;     /* P1-P2 : adresse */
    ControlPort.params[2] = adresse >> 8;
    return qd(15);
}
static void ecrire_qd(const uint8_t *s) {       /* 32,16 Draw String : chaîne précédée de sa longueur */
    libre();
    ControlPort.params[0] = (uint16_t)s & 0xFF;
    ControlPort.params[1] = (uint16_t)s >> 8;
    qd(16);
}

static const uint8_t faux[] = {'X', 'F', 1, 8, 'A', 1, 1, 1};
static const uint8_t texte[] = "\x01" "A";

int main(void) {
    putchar(12);
    init_graf();
    uint8_t e = choisir_police(0x00, (uint16_t)police);   /* Set Font */
    couleur(6);
    qd_xy(5, 100, 100);
    ecrire_qd(texte);                           /* 32,16 : le « A » de la police, un cadre 8x8 */
    uint8_t coin = px(100, 100), milieu = px(104, 104);
    uint8_t f = choisir_police(0x00, (uint16_t)faux);   /* en-tête faux : refusé */
    choisir_police(0x00, 0);                    /* page 0, adresse 0 : police intégrée */
    init_graf();
    printf("Police : erreur %u ; coin %u, milieu %u\n", e, coin, milieu);
    printf("En-tete faux : erreur %u\n", f);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Police : erreur 0 ; coin 6, milieu 0
En-tete faux : erreur 1
Mad Pascal
// Choisir une police proportionnelle (groupe 32, fonction 15, Trinity).
program qd15;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

// Une police NF1 d'un seul caractère, « A » : en-tête puis largeur et 8 rangées (bit 7 = pixel de gauche).
const police: array[0..16] of byte = (ord('N'), ord('F'), 1, 8, ord('A'), 1, 1, 1,   // NF, version 1, hauteur 8, premier « A », 1 caractère, espacement 1, 1 octet par rangée
                                       8, $FF, $81, $81, $81, $81, $81, $81, $FF);   // largeur 8 : un cadre
function choisir_police(page: byte; adresse: word): byte;   // 32,15 Set Font
begin
  NeoWaitMessage;
  NeoMessage.params[0] := page;                 // P0 : page ($00 RAM du 6502, $90 mémoire graphique)
  wordxParams[0] := adresse;                    // P1-P2 : adresse
  result := qd(15);
end;
procedure ecrire_qd(s: pointer);                // 32,16 Draw String : chaîne précédée de sa longueur
begin
  qd_rect(16, s);
end;

const faux: array[0..7] of byte = (ord('X'), ord('F'), 1, 8, ord('A'), 1, 1, 1);
      texte: array[0..1] of byte = (1, ord('A'));   // chaîne précédée de sa longueur
var e, f, coin, milieu: byte;
begin
  write(chr(12));
  init_graf;
  e := choisir_police($00, word(@police));      // Set Font
  couleur(6);
  qd_xy(5, 100, 100);
  ecrire_qd(@texte);                            // 32,16 : le « A » de la police, un cadre 8x8
  coin := NeoGetPixel(100, 100);
  milieu := NeoGetPixel(104, 104);
  f := choisir_police($00, word(@faux));        // en-tête faux : refusé
  choisir_police($00, 0);                       // page 0, adresse 0 : police intégrée
  init_graf;
  writeln('Police : erreur ', e, ' ; coin ', coin, ', milieu ', milieu);
  writeln('En-tete faux : erreur ', f);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Police : erreur 0 ; coin 6, milieu 0
En-tete faux : erreur 1
NeoBASIC
10 ' Choisir une police proportionnelle (groupe 32, fonction 15, Trinity)
20 cls : gosub 9400
30 po = alloc(17) : for i = 0 to 16 : read v : poke po + i, v : next i
40 data 78, 70, 1, 8, 65, 1, 1, 1 : ' NF, version 1, hauteur 8, premier A, 1 caractere, espacement 1, 1 octet par rangee
50 data 8, 255, 129, 129, 129, 129, 129, 129, 255 : ' largeur 8 : un cadre
60 fx = alloc(8) : for i = 0 to 7 : poke fx + i, peek(po + i) : next i : poke fx, asc("X") : ' en-tete faux
70 t = alloc(2) : poke t, 1 : poke t + 1, asc("A")
80 pg = 0 : ad = po : gosub 2000 : e1 = e : ' Set Font
90 c = 6 : gosub 9300 : x = 100 : y = 100 : f = 5 : gosub 9200
100 a = t : f = 16 : gosub 9000 : ' 32,16 : le A de la police, un cadre 8x8
110 co = point(100, 100) : mi = point(104, 104)
120 ad = fx : gosub 2000 : e2 = e : ' en-tete faux : refuse
130 ad = 0 : gosub 2000 : ' page 0, adresse 0 : police integree
140 gosub 9400
150 print "Police : erreur ";e1;" ; coin ";co;", milieu ";mi
160 print "En-tete faux : erreur ";e2
170 end
2000 ' Set Font : page pg, adresse ad
2010 while peek($ff00) : wend : poke $ff04, pg : doke $ff05, ad : f = 15 : gosub 9110
2020 return
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Police : erreur 0 ; coin 6, milieu 0
En-tete faux : erreur 1
65C02 assembly (64tass)
; Choisir une police proportionnelle (groupe 32, fonction 15, 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 #12                    ; écran effacé : on relit des pixels
        jsr WriteCharacter
        lda #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda ControlPort+2
        sta e1
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #<b3
        ldx #>b3
        jsr envoi
        lda #<b4
        ldx #>b4
        jsr envoi
        lda #100
        ldy #100
        jsr pixel
        sta co
        lda #104
        ldy #104
        jsr pixel
        sta mi
        lda #<b5
        ldx #>b5
        jsr envoi
        lda ControlPort+2
        sta e2
        lda #<b6
        ldx #>b6
        jsr envoi
        lda #<b7
        ldx #>b7
        jsr envoi
        lda #<t8
        ldx #>t8
        jsr ecrire
        lda e1
        jsr decimal
        lda #<t9
        ldx #>t9
        jsr ecrire
        lda co
        jsr decimal
        lda #<t10
        ldx #>t10
        jsr ecrire
        lda mi
        jsr decimal
        lda #13
        jsr WriteCharacter
        lda #<t11
        ldx #>t11
        jsr ecrire
        lda e2
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel:  pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0-P1 : X
        stz ControlPort+5
        sty ControlPort+6          ; P2-P3 : Y
        stz ControlPort+7
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

police: .text "NF"                 ; en-tête
        .byte 1, 8, 'A', 1         ; version 1, hauteur 8, premier A, 1 caractère
        .byte 1, 1                 ; espacement 1, 1 octet par rangée
        .byte 8, $FF, $81, $81, $81, $81, $81, $81, $FF   ; largeur 8 : un cadre
faux:   .text "XF"                 ; en-tête faux
        .byte 1, 8, 'A', 1, 1, 1
texte:  .byte 1, 'A'
b0:     .byte 32, 1, 0             ; 32,1 : Init Graf
b1:     .byte 32, 15, 3, 0         ; Set Font : page 0, adresse
        .word police
e1:     .byte 0
b2:     .byte 32, 4, 1, 6          ; 32,4 : Set Pen Colour
b3:     .byte 32, 5, 4             ; 32,5 : Move To
        .word 100, 100
b4:     .byte 32, 16, 2            ; 32,16 : le A de la police, un cadre 8x8
        .word texte
co:     .byte 0
mi:     .byte 0
b5:     .byte 32, 15, 3, 0         ; en-tête faux : refusé
        .word faux
e2:     .byte 0
b6:     .byte 32, 15, 3, 0         ; page 0, adresse 0 : police intégrée
        .word 0
b7:     .byte 32, 1, 0             ; 32,1 : Init Graf
t8:     .text "Police : erreur ", 0
t9:     .text " ; coin ", 0
t10:    .text ", milieu ", 0
t11:    .text "En-tete faux : erreur ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Police : erreur 0 ; coin 6, milieu 0
En-tete faux : erreur 1

32,16 Draw String Trinity

Writes a string with the current font, top left corner at the pen, in the pen colour; the pen moves on.

Inputs
BytesTypeMeaning
P0-P1addraddress of the string, preceded by its length

Outputs: none.

The unset pixels of characters leave the background alone (transparency). The pen moves on by the width of each character plus the font spacing: "AB" in the built-in 6 × 8 font takes it from x = 100 to 112. Characters missing from the font are skipped without moving. NeoBASIC has no keyword for this call.

Firmware documentation text

Draws the length-prefixed string at Parameters:0,1 with the current font, top left at the pen, set pixels in the pen colour, other pixels untouched (transparent), clipped ; the pen advances by the width of each glyph plus the font spacing. Characters absent from the font are skipped without advance.

C (llvm-mos)
/* Écrire un texte à la plume (groupe 32, fonction 16, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static int16_t plume_x, plume_y;
static uint8_t plume_c;

static void get_pen(void) {                     /* 32,6 Get Pen */
    libre();
    qd(6);
    plume_x = ControlPort.params[0] | ControlPort.params[1] << 8;
    plume_y = ControlPort.params[2] | ControlPort.params[3] << 8;
    plume_c = ControlPort.params[4];
}

/* Une police NF1 d'un seul caractère, « A » : en-tête puis largeur et 8 rangées (bit 7 = pixel de gauche). */
static const uint8_t police[] = {'N', 'F', 1, 8, 'A', 1, 1, 1,   /* NF, version 1, hauteur 8, premier « A », 1 caractère, espacement 1, 1 octet par rangée */
                                 8, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF};   /* largeur 8 : un cadre */
static uint8_t choisir_police(uint8_t page, uint16_t adresse) {   /* 32,15 Set Font */
    libre();
    ControlPort.params[0] = page;               /* P0 : page ($00 RAM du 6502, $90 mémoire graphique) */
    ControlPort.params[1] = adresse & 0xFF;     /* P1-P2 : adresse */
    ControlPort.params[2] = adresse >> 8;
    return qd(15);
}
static void ecrire_qd(const uint8_t *s) {       /* 32,16 Draw String : chaîne précédée de sa longueur */
    libre();
    ControlPort.params[0] = (uint16_t)s & 0xFF;
    ControlPort.params[1] = (uint16_t)s >> 8;
    qd(16);
}

static const uint8_t texte[] = "\x02" "AB";

int main(void) {
    putchar(12);
    init_graf();                                /* police intégrée 6x8 */
    couleur(6);
    qd_xy(5, 100, 100);
    ecrire_qd(texte);                           /* Draw String : en haut à gauche à la plume */
    get_pen();
    uint8_t n = 0;
    for (uint8_t y = 100; y < 108; y++)
        for (uint8_t x = 100; x < 112; x++)
            n += px(x, y) == 6;
    init_graf();
    printf("Plume apres AB : %d, %d ; pixels allumes : %u\n", plume_x, plume_y, n);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume apres AB : 112, 100 ; pixels allumes : 35
Mad Pascal
// Écrire un texte à la plume (groupe 32, fonction 16, Trinity).
program qd16;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

var plume_x, plume_y: smallint;
    plume_c: byte;

procedure get_pen;                              // 32,6 Get Pen
begin
  NeoWaitMessage;
  qd(6);
  plume_x := smallint(wordParams[0]);
  plume_y := smallint(wordParams[1]);
  plume_c := NeoMessage.params[4];
end;

// Une police NF1 d'un seul caractère, « A » : en-tête puis largeur et 8 rangées (bit 7 = pixel de gauche).
const police: array[0..16] of byte = (ord('N'), ord('F'), 1, 8, ord('A'), 1, 1, 1,   // NF, version 1, hauteur 8, premier « A », 1 caractère, espacement 1, 1 octet par rangée
                                       8, $FF, $81, $81, $81, $81, $81, $81, $FF);   // largeur 8 : un cadre
function choisir_police(page: byte; adresse: word): byte;   // 32,15 Set Font
begin
  NeoWaitMessage;
  NeoMessage.params[0] := page;                 // P0 : page ($00 RAM du 6502, $90 mémoire graphique)
  wordxParams[0] := adresse;                    // P1-P2 : adresse
  result := qd(15);
end;
procedure ecrire_qd(s: pointer);                // 32,16 Draw String : chaîne précédée de sa longueur
begin
  qd_rect(16, s);
end;

const texte: string[2] = 'AB';
var n, x, y: byte;
begin
  write(chr(12));
  init_graf;                                    // police intégrée 6x8
  couleur(6);
  qd_xy(5, 100, 100);
  ecrire_qd(@texte);                            // Draw String : en haut à gauche à la plume
  get_pen;
  n := 0;
  for y := 100 to 107 do
    for x := 100 to 111 do
      if NeoGetPixel(x, y) = 6 then inc(n);
  init_graf;
  writeln('Plume apres AB : ', plume_x, ', ', plume_y, ' ; pixels allumes : ', n);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume apres AB : 112, 100 ; pixels allumes : 35
NeoBASIC
10 ' Ecrire un texte a la plume (groupe 32, fonction 16, Trinity)
20 cls : gosub 9400 : ' police integree 6x8
30 t = alloc(3) : poke t, 2 : poke t + 1, asc("A") : poke t + 2, asc("B")
40 c = 6 : gosub 9300 : x = 100 : y = 100 : f = 5 : gosub 9200
50 a = t : f = 16 : gosub 9000 : ' Draw String : en haut a gauche a la plume
60 gosub 9500
70 n = 0 : for y = 100 to 107 : for x = 100 to 111 : if point(x, y) = 6 then n = n + 1
80 next x : next y
90 gosub 9400
100 print "Plume apres AB : ";px;", ";py;" ; pixels allumes : ";n
110 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
9500 ' 32,6 Get Pen : px, py, pc
9510 while peek($ff00) : wend : f = 6 : gosub 9110
9520 px = deek($ff04) : py = deek($ff06) : pc = peek($ff08)
9530 if px > 32767 then px = px - 65536
9540 if py > 32767 then py = py - 65536
9550 return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume apres AB : 112, 100 ; pixels allumes : 35
65C02 assembly (64tass)
; Écrire un texte à la plume (groupe 32, fonction 16, 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 #12                    ; écran effacé : on relit des pixels
        jsr WriteCharacter
        lda #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #<b3
        ldx #>b3
        jsr envoi
        lda #<b5
        ldx #>b5
        jsr envoi
        ldx #4
_c4:   lda ControlPort+4,x
        sta pen,x
        dex
        bpl _c4
        stz n                      ; pixels de couleur 6 dans x 100 à 111, y 100 à 107
        lda #100
        sta yy
_y:     lda #100
        sta xx
_x:     lda xx
        ldy yy
        jsr pixel
        cmp #6
        bne _nx
        inc n
_nx:    inc xx
        lda xx
        cmp #112
        bne _x
        inc yy
        lda yy
        cmp #108
        bne _y
        lda #<b6
        ldx #>b6
        jsr envoi
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda pen
        ldx pen+1
        jsr dec16
        lda #<t8
        ldx #>t8
        jsr ecrire
        lda pen+2
        ldx pen+2+1
        jsr dec16
        lda #<t9
        ldx #>t9
        jsr ecrire
        lda n
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel:  pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0-P1 : X
        stz ControlPort+5
        sty ControlPort+6          ; P2-P3 : Y
        stz ControlPort+7
        lda #5
        ldx #33                    ; 5,33 : Read Pixel
        jsr appel
        lda ControlPort+4
        rts

texte:  .byte 2
        .text "AB"
n:      .byte 0
xx:     .byte 0
yy:     .byte 0
b0:     .byte 32, 1, 0             ; police intégrée 6x8
b1:     .byte 32, 4, 1, 6          ; 32,4 : Set Pen Colour
b2:     .byte 32, 5, 4             ; 32,5 : Move To
        .word 100, 100
b3:     .byte 32, 16, 2            ; Draw String : en haut à gauche à la plume
        .word texte
b5:     .byte 32, 6, 0             ; 32,6 : Get Pen
pen:    .fill 5                    ; x, y (16 bits), couleur
b6:     .byte 32, 1, 0             ; 32,1 : Init Graf
t7:     .text "Plume apres AB : ", 0
t8:     .text ", ", 0
t9:     .text " ; pixels allumes : ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume apres AB : 112, 100 ; pixels allumes : 35

32,17 Text Width Trinity

Returns the width in pixels a string would take when written by 32,16, without drawing anything.

Inputs
BytesTypeMeaning
P0-P1addraddress of the string, preceded by its length
Outputs
BytesTypeMeaning
P2-P3uint16width in pixels

In the built-in font, each character counts 6 pixels: "Neo6502" takes 42. NeoBASIC has no keyword for this call.

Firmware documentation text

Returns in Parameters:2,3 the width in pixels the string at Parameters:0,1 would take with Draw String.

C (llvm-mos)
/* Mesurer un texte avant de l'écrire (groupe 32, fonction 17, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static const uint8_t texte[] = "\x07" "Neo6502";

static uint16_t largeur(const uint8_t *s) {     /* Text Width */
    libre();
    ControlPort.params[0] = (uint16_t)s & 0xFF;
    ControlPort.params[1] = (uint16_t)s >> 8;
    qd(17);
    return ControlPort.params[2] | ControlPort.params[3] << 8;
}

int main(void) {
    init_graf();                                /* police intégrée 6x8 */
    printf("Neo6502 : %u pixels\n", largeur(texte));
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Neo6502 : 42 pixels
Mad Pascal
// Mesurer un texte avant de l'écrire (groupe 32, fonction 17, Trinity).
program qd17;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

const texte: string[7] = 'Neo6502';
var l: word;
begin
  init_graf;                                    // police intégrée 6x8
  qd_rect(17, @texte);                          // Text Width
  l := wordParams[1];                           // P2-P3 : largeur en pixels
  writeln('Neo6502 : ', l, ' pixels');
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Neo6502 : 42 pixels
NeoBASIC
10 ' Mesurer un texte avant de l'ecrire (groupe 32, fonction 17, Trinity)
20 gosub 9400 : ' police integree 6x8
30 t = alloc(8) : t$ = "Neo6502" : poke t, len(t$) : for i = 1 to len(t$) : poke t + i, asc(mid$(t$, i, 1)) : next i
40 a = t : f = 17 : gosub 9000 : l = deek($ff06) : ' Text Width : largeur en P2-P3
50 print "Neo6502 : ";l;" pixels"
60 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Neo6502 : 42 pixels
65C02 assembly (64tass)
; Mesurer un texte avant de l'écrire (groupe 32, fonction 17, 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 #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda ControlPort+6          ; P2-P3 : largeur en pixels
        sta l
        lda ControlPort+7
        sta l+1
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda l
        ldx l+1
        jsr dec16
        lda #<t3
        ldx #>t3
        jsr ecrire
        lda #13
        jsr WriteCharacter
        rts

texte:  .byte 7
        .text "Neo6502"
b0:     .byte 32, 1, 0             ; police intégrée 6x8
b1:     .byte 32, 17, 2            ; Text Width : largeur en P2-P3
        .word texte
l:      .word 0
t2:     .text "Neo6502 : ", 0
t3:     .text " pixels", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Neo6502 : 42 pixels

32,18 Get Font Info Trinity

Returns the height, the first character and the character count of the current font.

Inputs: none.

Outputs
BytesTypeMeaning
P0uint8height in pixels
P1uint8first character
P2uint8character count

The built-in font is 8 pixels high and covers the 96 characters from 32 (space) to 127. NeoBASIC has no keyword for this call.

Firmware documentation text

Returns the height of the current font in Parameter:0, its first character in Parameter:1 and its character count in Parameter:2.

C (llvm-mos)
/* Lire la hauteur et les caractères de la police (groupe 32, fonction 18, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

int main(void) {
    init_graf();                                /* police intégrée */
    libre();
    qd(18);                                     /* Get Font Info */
    printf("Hauteur %u, premier caractere %u, %u caracteres\n",
           ControlPort.params[0], ControlPort.params[1], ControlPort.params[2]);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Hauteur 8, premier caractere 32, 96 caracteres
Mad Pascal
// Lire la hauteur et les caractères de la police (groupe 32, fonction 18, Trinity).
program qd18;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

var h, p, n: byte;
begin
  init_graf;                                    // police intégrée
  NeoWaitMessage;
  qd(18);                                       // Get Font Info
  h := NeoMessage.params[0];
  p := NeoMessage.params[1];
  n := NeoMessage.params[2];
  writeln('Hauteur ', h, ', premier caractere ', p, ', ', n, ' caracteres');
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Hauteur 8, premier caractere 32, 96 caracteres
NeoBASIC
10 ' Lire la hauteur et les caracteres de la police (groupe 32, fonction 18, Trinity)
20 gosub 9400 : ' police integree
30 while peek($ff00) : wend : f = 18 : gosub 9110 : ' Get Font Info
40 h = peek($ff04) : p = peek($ff05) : n = peek($ff06)
50 print "Hauteur ";h;", premier caractere ";p;", ";n;" caracteres"
60 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Hauteur 8, premier caractere 32, 96 caracteres
65C02 assembly (64tass)
; Lire la hauteur et les caractères de la police (groupe 32, fonction 18, 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 #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda ControlPort+4          ; hauteur
        sta h
        lda ControlPort+5          ; premier caractère
        sta pr
        lda ControlPort+6          ; nombre de caractères
        sta nb
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda h
        jsr decimal
        lda #<t3
        ldx #>t3
        jsr ecrire
        lda pr
        jsr decimal
        lda #<t4
        ldx #>t4
        jsr ecrire
        lda nb
        jsr decimal
        lda #<t5
        ldx #>t5
        jsr ecrire
        lda #13
        jsr WriteCharacter
        rts

b0:     .byte 32, 1, 0             ; police intégrée
b1:     .byte 32, 18, 0            ; Get Font Info
h:      .byte 0
pr:     .byte 0
nb:     .byte 0
t2:     .text "Hauteur ", 0
t3:     .text ", premier caractere ", 0
t4:     .text ", ", 0
t5:     .text " caracteres", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Hauteur 8, premier caractere 32, 96 caracteres

32,19 Toolbox Reset Trinity

Puts the whole Trinity toolbox back in its start-up state: no window, menu, control or dialog left, QuickDraw as after 32,1.

Inputs: none.

Outputs: none.

Nothing is drawn or erased. The toolbox keeps its state from one program to the next: according to the Trinity documentation, NeoDOS is to call this function when a program returns to it, and a program may also call it first thing. Unlike 32,1, it is not meant to be called while the program has windows open. The example changes the pen and the clip, then reads them back after the call. NeoBASIC has no keyword for this call.

Firmware documentation text

Puts the whole toolbox back in its start up state (Trinity T-88) : no window, no menu (and the menu bar back to the full width, Function 35,9), no control, no dialog, event manager off, no resource file, QuickDraw as after 32,1. Nothing is drawn or erased. The toolbox otherwise keeps its state from one program to the next : NeoDOS is to call this when a program returns to it (T-88, asked of NeoDOS), so the next program does not inherit its menus or windows. A program may call it first thing as well. Unlike 32,1, which a program may call again while its windows exist.

C (llvm-mos)
/* Remettre toute la boîte à outils dans son état de départ (groupe 32, fonction 19, Trinity). */
#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)
        ;
}

/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;

static uint8_t qd(uint8_t f) {                  /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
    api(32, f);
    return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) {    /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
    libre();
    ControlPort.params[0] = (uint16_t)r & 0xFF;
    ControlPort.params[1] = (uint16_t)r >> 8;
    return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) {   /* 32,5 Move To ou 32,11 Line To */
    libre();
    ControlPort.params[0] = x & 0xFF;
    ControlPort.params[1] = x >> 8;
    ControlPort.params[2] = y & 0xFF;
    ControlPort.params[3] = y >> 8;
    qd(f);
}
static void couleur(uint8_t c) {                /* 32,4 Set Pen Colour */
    libre();
    ControlPort.params[0] = c;
    qd(4);
}
static void init_graf(void) {                   /* 32,1 Init Graf */
    libre();
    qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) {     /* 5,33 : couleur du pixel */
    return neo_graphics_read_pixel(x, y);
}

static int16_t plume_x, plume_y;
static uint8_t plume_c;

static void get_pen(void) {                     /* 32,6 Get Pen */
    libre();
    qd(6);
    plume_x = ControlPort.params[0] | ControlPort.params[1] << 8;
    plume_y = ControlPort.params[2] | ControlPort.params[3] << 8;
    plume_c = ControlPort.params[4];
}

static Rect clip;
static void get_clip(void) {                    /* 32,3 Get Clip : écrit le rectangle de découpe dans clip */
    qd_rect(3, &clip);
}

static Rect zone = {10, 10, 50, 50};

int main(void) {
    couleur(9);                                 /* un état quelconque */
    qd_xy(5, 30, 30);
    qd_rect(2, &zone);
    libre();
    qd(19);                                     /* Toolbox Reset */
    get_pen();
    get_clip();
    printf("Plume : %d, %d, couleur %u ; decoupe : %d, %d, %d, %d\n",
           plume_x, plume_y, plume_c, clip.g, clip.h, clip.d, clip.b);
    return 0;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 0, 0, couleur 15 ; decoupe : 0, 0, 320, 240
Mad Pascal
// Remettre toute la boîte à outils dans son état de départ (groupe 32, fonction 19, Trinity).
program qd19;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)

function qd(f: byte): byte;                     // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
  NeoSendMessage(32, f);
  NeoWaitMessage;
  result := NeoMessage.error;
end;

function qd_rect(f: byte; r: pointer): byte;    // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
  NeoWaitMessage;
  wordParams[0] := word(r);
  result := qd(f);
end;

procedure qd_xy(f: byte; x, y: smallint);       // 32,5 Move To ou 32,11 Line To
begin
  NeoWaitMessage;
  wordParams[0] := word(x);
  wordParams[1] := word(y);
  qd(f);
end;

procedure couleur(c: byte);                     // 32,4 Set Pen Colour
begin
  NeoWaitMessage;
  NeoMessage.params[0] := c;
  qd(4);
end;

procedure init_graf;                            // 32,1 Init Graf
begin
  NeoWaitMessage;
  qd(1);
end;

var plume_x, plume_y: smallint;
    plume_c: byte;

procedure get_pen;                              // 32,6 Get Pen
begin
  NeoWaitMessage;
  qd(6);
  plume_x := smallint(wordParams[0]);
  plume_y := smallint(wordParams[1]);
  plume_c := NeoMessage.params[4];
end;

var clip: Rect;
procedure get_clip;                             // 32,3 Get Clip : écrit le rectangle de découpe dans clip
begin
  qd_rect(3, @clip);
end;

var zone: Rect;
begin
  zone.g := 10; zone.h := 10; zone.d := 50; zone.b := 50;
  couleur(9);                                   // un état quelconque
  qd_xy(5, 30, 30);
  qd_rect(2, @zone);
  NeoWaitMessage;
  qd(19);                                       // Toolbox Reset
  get_pen;
  get_clip;
  writeln('Plume : ', plume_x, ', ', plume_y, ', couleur ', plume_c, ' ; decoupe : ', clip.g, ', ', clip.h, ', ', clip.d, ', ', clip.b);
end.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 0, 0, couleur 15 ; decoupe : 0, 0, 320, 240
NeoBASIC
10 ' Remettre toute la boite a outils dans son etat de depart (groupe 32, fonction 19, Trinity)
20 k = alloc(8) : q = alloc(8) : g = 10 : h = 10 : d = 50 : b = 50 : gosub 8000
30 c = 9 : gosub 9300 : x = 30 : y = 30 : f = 5 : gosub 9200 : a = q : f = 2 : gosub 9000 : ' un etat quelconque
40 while peek($ff00) : wend : f = 19 : gosub 9110 : ' Toolbox Reset
50 gosub 9500 : gosub 9600
60 print "Plume : ";px;", ";py;", couleur ";pc;" ; decoupe : ";cg;", ";ch;", ";cd;", ";cb
70 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
9500 ' 32,6 Get Pen : px, py, pc
9510 while peek($ff00) : wend : f = 6 : gosub 9110
9520 px = deek($ff04) : py = deek($ff06) : pc = peek($ff08)
9530 if px > 32767 then px = px - 65536
9540 if py > 32767 then py = py - 65536
9550 return
9600 ' 32,3 Get Clip dans le Rect k ; valeurs dans cg, ch, cd, cb
9610 a = k : f = 3 : gosub 9000
9620 cg = deek(k) : ch = deek(k + 2) : cd = deek(k + 4) : cb = deek(k + 6)
9630 return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 0, 0, couleur 15 ; decoupe : 0, 0, 320, 240
65C02 assembly (64tass)
; Remettre toute la boîte à outils dans son état de départ (groupe 32, fonction 19, 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 #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #<b3
        ldx #>b3
        jsr envoi
        lda #<b5
        ldx #>b5
        jsr envoi
        ldx #4
_c4:   lda ControlPort+4,x
        sta pen,x
        dex
        bpl _c4
        lda #<b6
        ldx #>b6
        jsr envoi
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda pen
        ldx pen+1
        jsr dec16
        lda #<t8
        ldx #>t8
        jsr ecrire
        lda pen+2
        ldx pen+2+1
        jsr dec16
        lda #<t9
        ldx #>t9
        jsr ecrire
        lda pen+4
        jsr decimal
        lda #<t10
        ldx #>t10
        jsr ecrire
        lda k
        ldx k+1
        jsr dec16
        lda #<t11
        ldx #>t11
        jsr ecrire
        lda k+2
        ldx k+2+1
        jsr dec16
        lda #<t12
        ldx #>t12
        jsr ecrire
        lda k+4
        ldx k+4+1
        jsr dec16
        lda #<t13
        ldx #>t13
        jsr ecrire
        lda k+6
        ldx k+6+1
        jsr dec16
        lda #13
        jsr WriteCharacter
        rts

q:      .word 10, 10, 50, 50          ; gauche, haut, droite, bas (droite et bas exclus)
k:      .fill 8
b0:     .byte 32, 4, 1, 9          ; un état quelconque : couleur 9...
b1:     .byte 32, 5, 4             ; 32,5 : Move To
        .word 30, 30
b2:     .byte 32, 2, 2             ; ... plume en (30, 30), découpe réduite
        .word q
b3:     .byte 32, 19, 0            ; Toolbox Reset
b5:     .byte 32, 6, 0             ; 32,6 : Get Pen
pen:    .fill 5                    ; x, y (16 bits), couleur
b6:     .byte 32, 3, 2             ; 32,3 : Get Clip
        .word k
t7:     .text "Plume : ", 0
t8:     .text ", ", 0
t9:     .text ", couleur ", 0
t10:    .text " ; decoupe : ", 0
t11:    .text ", ", 0
t12:    .text ", ", 0
t13:    .text ", ", 0

; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi:  sta blk
        stx blk+1
        jsr WaitMessage
        ldy #2
        lda (blk),y                ; nombre de paramètres
        clc
        adc #3
        sta fin
        ldy #3
_copie: cpy fin
        beq _lance
        lda (blk),y
        sta ControlPort+1,y        ; octet 3 du bloc -> P0 ($FF04)...
        iny
        bra _copie
_lance: ldy #1
        lda (blk),y
        tax
        lda (blk)
        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

; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16:  sta n16
        stx n16+1
        stz vu
        ldy #0                     ; puissance de 10 en cours : 10000, 1000, 100, 10
_p:     ldx #0                     ; chiffre
_s:     lda n16
        sec
        sbc p10l,y
        pha
        lda n16+1
        sbc p10h,y
        bcc _neg                   ; plus petit : chiffre trouvé
        sta n16+1
        pla
        sta n16
        inx
        bra _s
_neg:   pla
        txa
        ora vu
        beq _suiv                  ; pas de zéro de tête
        txa
        ora #'0'
        phy
        jsr WriteCharacter
        ply
        lda #1
        sta vu
_suiv:  iny
        cpy #4
        bne _p
        lda n16                    ; les unités, toujours
        ora #'0'
        jmp WriteCharacter
p10l:   .byte <10000, <1000, <100, <10
p10h:   .byte >10000, >1000, >100, >10
n16:    .word 0
vu:     .byte 0

; 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
blk      = $82
diviseur: .byte 0
fin:     .byte 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Plume : 0, 0, couleur 15 ; decoupe : 0, 0, 320, 240

← The Neo6502 API