Tachibana
Langue : français

Groupe 37 — Gestionnaire de dialogues Trinity

37,1 New Dialog · 37,2 Dispose Dialog · 37,3 Dialog Event · 37,4 Get Dialog Item · 37,5 Draw Dialog · 37,6 Alert

Le gestionnaire de dialogues de la boîte à outils de Trinity construit des dialogues modaux (2 au plus) et des alertes, avec les fenêtres (groupe 34) et les contrôles (groupe 36).

Descripteur d'un dialogue, en RAM du 6502 : le Rect de la fenêtre (coordonnées de l'écran), un octet d'options (bit 0 barre de titre), le titre précédé de sa longueur ; puis jusqu'à 12 éléments terminés par un octet 0, chacun : type (1 bouton, 2 case à cocher, 3 bouton radio, 4 barre de défilement, 5 champ de texte, 6 texte fixe), options (bit 0 inactif, bit 1 par défaut, déclenché par Entrée, bit 2 annulation, déclenché par Échap), Rect relatif au contenu, maximum sur 16 bits (valeur d'une barre ou longueur d'un champ), texte précédé de sa longueur (un champ de texte réserve 1 + maximum octets ; un texte fixe passe à la ligne à chaque caractère 13).

Le dialogue des exemples : « Reglages », avec OK (par défaut), Annuler (annulation), une case « Son », un champ de texte « ab » de 8 caractères au plus et un texte fixe. Les exemples fabriquent les événements qu'ils lui passent et remettent la boîte à outils à zéro avec 32,19 au début et à la fin.

37,1 New Dialog Trinity

Construit un dialogue modal à partir d'un descripteur en RAM du 6502 et le dessine.

Entrées
OctetsTypeRôle
P0-P1addradresse du descripteur (lu sur place)
Sorties
OctetsTypeRôle
P2uint8numéro du dialogue (1 ou 2)
P3uint8sa fenêtre (groupe 34)
erreuruint81 descripteur invalide, 2 plus de dialogue, de fenêtre ou de contrôle libre

Le descripteur (voir l'introduction) doit rester intact tant que le dialogue est ouvert : le firmware le relit et écrit dans le tampon des champs de texte. Les éléments 1 à 5 sont des contrôles du groupe 36 (voir 37,4). Les touches vont au premier champ de texte actif (Tab : au suivant). Un type d'élément inconnu est refusé. NeoBASIC n'a pas de mot-clé pour cet appel.

Texte de la documentation du firmware (anglais)

Toolbox (Trinity, T-12, ADR-01 of the fork). Builds a modal dialog from the descriptor at Parameters:0,1 in 6502 RAM and returns its number (1-2) in Parameter:2 and its window (group 34) in Parameter:3 (error 1 bad descriptor, 2 no dialog, window or control left). The descriptor is read in place and must stay intact : the screen Rect of the window, a flags byte (bit 0 title bar), the length-prefixed title, then up to 12 items ended by a 0 byte, each : kind (1 button, 2 check box, 3 radio, 4 scroll bar, 5 text field, 6 static text), flags (bit 0 disabled, bit 1 default - fired by Return, drawn with a ring -, bit 2 cancel - fired by Escape), Rect relative to the content, a 16 bit maximum (scroll bar value / text field length) and the length-prefixed title, text or buffer (a text field reserves 1 + maximum bytes ; static text : one line per character 13). Items 1-5 are controls of group 36 (see Get Dialog Item) ; the dialog is drawn at once and again on its update events through Dialog Event. Keys go to the first enabled text field (Tab : next one).

C (llvm-mos)
/* Ouvrir un dialogue (groupe 37, 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)
        ;
}

/* Descripteur de dialogue, lu sur place : Rect de la fenêtre (écran), options (bit 0 barre de titre), titre ;
   puis chaque élément : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ de texte, 6 texte fixe), options
   (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation : Échap), Rect relatif au contenu, maximum,
   texte précédé de sa longueur (un champ de texte réserve 1 + maximum octets) ; un 0 termine la liste. */
#define W(v) (v) & 0xFF, (v) >> 8
static uint8_t reglages[] = {
    W(40), W(40), W(240), W(160), 1, 8, 'R', 'e', 'g', 'l', 'a', 'g', 'e', 's',
    1, 2, W(130), W(90), W(190), W(104), W(0), 2, 'O', 'K',                          /* 1 : bouton par défaut */
    1, 4, W(60), W(90), W(120), W(104), W(0), 7, 'A', 'n', 'n', 'u', 'l', 'e', 'r',   /* 2 : annulation */
    2, 0, W(10), W(10), W(100), W(22), W(0), 3, 'S', 'o', 'n',                 /* 3 : case à cocher */
    5, 0, W(10), W(30), W(150), W(44), W(8), 2, 'a', 'b', 0, 0, 0, 0, 0, 0,      /* 4 : champ de texte, 8 au plus */
    6, 0, W(10), W(50), W(150), W(60), W(0), 7, 'B', 'o', 'n', 'j', 'o', 'u', 'r',   /* 5 : texte fixe */
    0 };
#define CHAMP 81                                /* position du tampon de l'élément 4 dans le descripteur */

static void p16(uint8_t i, uint16_t v) {        /* paramètre 16 bits en Pi, Pi+1 */
    ControlPort.params[i] = v & 0xFF;
    ControlPort.params[i + 1] = v >> 8;
}
static void reinit(void) {                      /* 32,19 Toolbox Reset */
    libre();
    api(32, 19);
}
static uint8_t dialogue, fenetre;
static uint8_t ouvrir(uint8_t *descripteur) {   /* 37,1 New Dialog : rend l'indicateur d'erreur */
    libre();
    p16(0, (uint16_t)descripteur);
    api(37, 1);
    dialogue = ControlPort.params[2];
    fenetre = ControlPort.params[3];
    return ControlPort.error;
}
static void fermer(uint8_t d) {                 /* 37,2 Dispose Dialog */
    libre();
    ControlPort.params[0] = d;
    api(37, 2);
}

int main(void) {
    uint8_t d, w, e;
    reinit();
    ouvrir(reglages);                           /* fenêtre et contrôles créés, dessinés aussitôt */
    d = dialogue; w = fenetre;
    fermer(d);
    reglages[18] = 9;                           /* type du premier élément (octet 18) : 9 n'existe pas */
    e = ouvrir(reglages);
    reglages[18] = 1;
    reinit();
    printf("Dialogue %u, fenetre %u ; type 9 : erreur %u\n", d, w, e);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Dialogue 1, fenetre 1 ; type 9 : erreur 1
Mad Pascal
// Ouvrir un dialogue (groupe 37, fonction 1, Trinity).
program dl1;
uses crt, neo6502;
// Descripteur de dialogue (variable : le firmware écrit dans le champ de texte), lu sur place : Rect de la
// fenêtre (écran), options (bit 0 barre de titre), titre ; puis chaque élément : type (1 bouton, 2 case, 3 radio,
// 4 barre, 5 champ de texte, 6 texte fixe), options (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation :
// Échap), Rect relatif au contenu, maximum, texte précédé de sa longueur (un champ de texte réserve 1 + maximum
// octets) ; un 0 termine la liste.
var reglages: array[0..110] of byte = (
    40, 0, 40, 0, 240, 0, 160, 0, 1, 8, ord('R'), ord('e'), ord('g'), ord('l'), ord('a'), ord('g'), ord('e'), ord('s'),
    1, 2, 130, 0, 90, 0, 190, 0, 104, 0, 0, 0, 2, ord('O'), ord('K'),   // 1 : bouton par défaut
    1, 4, 60, 0, 90, 0, 120, 0, 104, 0, 0, 0, 7, ord('A'), ord('n'), ord('n'), ord('u'), ord('l'), ord('e'), ord('r'),   // 2 : annulation
    2, 0, 10, 0, 10, 0, 100, 0, 22, 0, 0, 0, 3, ord('S'), ord('o'), ord('n'),   // 3 : case à cocher
    5, 0, 10, 0, 30, 0, 150, 0, 44, 0, 8, 0, 2, ord('a'), ord('b'), 0, 0, 0, 0, 0, 0,   // 4 : champ de texte, 8 au plus
    6, 0, 10, 0, 50, 0, 150, 0, 60, 0, 0, 0, 7, ord('B'), ord('o'), ord('n'), ord('j'), ord('o'), ord('u'), ord('r'),   // 5 : texte fixe
    0);
const CHAMP = 81;                               // position du tampon de l'élément 4 dans le descripteur

var dialogue, fenetre: byte;

procedure appel(g, f: byte);                    // appel g,f (paramètres déjà posés)
begin
  NeoSendMessage(g, f);
  NeoWaitMessage;
end;

procedure reinit;                               // 32,19 Toolbox Reset
begin
  NeoWaitMessage;
  appel(32, 19);
end;

function ouvrir(descripteur: pointer): byte;    // 37,1 New Dialog : rend l'indicateur d'erreur
begin
  NeoWaitMessage;
  wordParams[0] := word(descripteur);
  appel(37, 1);
  dialogue := NeoMessage.params[2];
  fenetre := NeoMessage.params[3];
  result := NeoMessage.error;
end;

procedure fermer(d: byte);                      // 37,2 Dispose Dialog
begin
  NeoWaitMessage;
  NeoMessage.params[0] := d;
  appel(37, 2);
end;

var d, w, e: byte;
begin
  reinit;
  ouvrir(@reglages);                            // fenêtre et contrôles créés, dessinés aussitôt
  d := dialogue; w := fenetre;
  fermer(d);
  reglages[18] := 9;                            // type du premier élément (octet 18) : 9 n'existe pas
  e := ouvrir(@reglages);
  reglages[18] := 1;
  reinit;
  writeln('Dialogue ', d, ', fenetre ', w, ' ; type 9 : erreur ', e);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Dialogue 1, fenetre 1 ; type 9 : erreur 1
NeoBASIC
10 ' Ouvrir un dialogue (groupe 37, fonction 1, Trinity)
15 gosub 7000
20 gosub 8300
30 q = rg : gosub 8000 : d = dg : w = fw : ' fenetre et controles crees, dessines aussitot
40 gosub 8200
50 poke rg + 18, 9 : ' type du premier element (octet 18) : 9 n'existe pas
60 gosub 8000 : e9 = e
70 poke rg + 18, 1 : gosub 8300
80 print "Dialogue ";d;", fenetre ";w;" ; type 9 : erreur ";e9
90 end
7000 ' descripteur de dialogue, lu sur place : Rect de la fenetre (ecran), options (bit 0 barre de titre), titre ;
7005 ' puis chaque element : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ, 6 texte fixe), options (bit 0 inactif,
7010 ' bit 1 par defaut : Entree, bit 2 annulation : Echap), Rect relatif au contenu, maximum, texte precede de sa
7015 ' longueur (un champ de texte reserve 1 + maximum octets) ; un 0 termine la liste. Adresse dans rg.
7020 rg = alloc(111) : p = rg
7025 for k = 1 to 4 : read v : doke p, v : p = p + 2 : next k : read v : poke p, v : p = p + 1 : read s$ : gosub 7100
7030 for it = 1 to 5 : read ty, op : poke p, ty : poke p + 1, op : p = p + 2
7035 for k = 1 to 5 : read v : doke p, v : p = p + 2 : next k : read s$ : p0 = p : gosub 7100
7040 if ty = 5 then p = p0 + 1 + v : ' le champ reserve 1 + maximum octets
7045 next it : poke p, 0 : ch = rg + 81 : return : ' ch : tampon de l'element 4
7050 data 40, 40, 240, 160, 1, "Reglages"
7055 data 1, 2, 130, 90, 190, 104, 0, "OK" : ' 1 : bouton par defaut
7060 data 1, 4, 60, 90, 120, 104, 0, "Annuler" : ' 2 : annulation
7065 data 2, 0, 10, 10, 100, 22, 0, "Son" : ' 3 : case a cocher
7070 data 5, 0, 10, 30, 150, 44, 8, "ab" : ' 4 : champ de texte, 8 au plus
7075 data 6, 0, 10, 50, 150, 60, 0, "Bonjour" : ' 5 : texte fixe
7100 poke p, len(s$) : for i = 1 to len(s$) : poke p + i, asc(mid$(s$, i, 1)) : next i : p = p + len(s$) + 1 : return
8000 ' 37,1 New Dialog sur le descripteur q : dialogue dans dg, fenetre dans fw, erreur dans e
8010 while peek($ff00) : wend : doke $ff04, q : f = 1 : gosub 8110
8020 dg = peek($ff06) : fw = peek($ff07) : return
8100 ' appel 37,f, parametres deja poses ; erreur dans e
8110 poke $ff01, f : poke $ff00, 37
8120 while peek($ff00) : wend : e = peek($ff02) : return
8200 ' 37,2 Dispose Dialog dg
8210 while peek($ff00) : wend : poke $ff04, dg : f = 2 : goto 8110
8300 ' 32,19 Toolbox Reset
8310 while peek($ff00) : wend : poke $ff01, 19 : poke $ff00, 32
8320 while peek($ff00) : wend : return
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Dialogue 1, fenetre 1 ; type 9 : erreur 1
Assembleur 65C02 (64tass)
; Ouvrir un dialogue (groupe 37, 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
        jsr ouvrir                 ; fenêtre et contrôles créés, dessinés aussitôt
        lda dlg
        sta d
        lda fen
        sta w
        lda dlg
        ldx #2                     ; 37,2
        jsr dial
        lda #9                     ; type du premier élément : 9 n'existe pas
        sta type1
        jsr ouvrir
        sta e
        lda #1
        sta type1
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda d
        jsr decimal
        lda #<t3
        ldx #>t3
        jsr ecrire
        lda w
        jsr decimal
        lda #<t4
        ldx #>t4
        jsr ecrire
        lda e
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Descripteur de dialogue, lu sur place : Rect de la fenêtre (écran), options (bit 0 barre de titre), titre ;
; puis chaque élément : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ de texte, 6 texte fixe), options
; (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation : Échap), Rect relatif au contenu, maximum,
; texte précédé de sa longueur (un champ de texte réserve 1 + maximum octets) ; un 0 termine la liste.
reglages: .word 40, 40, 240, 160
        .byte 1, 8
        .text "Reglages"
type1:  .byte 1, 2                 ; 1 : bouton par défaut
        .word 130, 90, 190, 104, 0
        .byte 2
        .text "OK"
        .byte 1, 4                 ; 2 : annulation
        .word 60, 90, 120, 104, 0
        .byte 7
        .text "Annuler"
        .byte 2, 0                 ; 3 : case à cocher
        .word 10, 10, 100, 22, 0
        .byte 3
        .text "Son"
        .byte 5, 0                 ; 4 : champ de texte, 8 au plus
        .word 10, 30, 150, 44, 8
champ:  .byte 2
        .text "ab"
        .fill 6
        .byte 6, 0                 ; 5 : texte fixe
        .word 10, 50, 150, 60, 0
        .byte 7
        .text "Bonjour"
        .byte 0
b0:     .byte 32, 19, 0            ; 32,19 Toolbox Reset
d:      .byte 0
w:      .byte 0
e:      .byte 0
b1:     .byte 32, 19, 0            ; 32,19 Toolbox Reset
t2:     .text "Dialogue ", 0
t3:     .text ", fenetre ", 0
t4:     .text " ; type 9 : 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

; 37,1 New Dialog sur le descripteur reglages : dialogue dans dlg, fenêtre dans fen ; erreur dans A.
ouvrir: jsr WaitMessage
        lda #<reglages
        sta ControlPort+4
        lda #>reglages
        sta ControlPort+5
        lda #37
        ldx #1
        jsr appel
        lda ControlPort+6
        sta dlg
        lda ControlPort+7
        sta fen
        lda ControlPort+2
        rts

; 37,X sur le dialogue A.
dial:   pha
        phx
        jsr WaitMessage
        plx
        pla
        sta ControlPort+4
        lda #37
        jmp appel

dlg:    .byte 0
fen:    .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
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Dialogue 1, fenetre 1 ; type 9 : erreur 1

37,2 Dispose Dialog Trinity

Ferme un dialogue : sa fenêtre et ses contrôles sont supprimés.

Entrées
OctetsTypeRôle
P0uint8numéro du dialogue

Sorties : aucune.

Les fenêtres qu'il couvrait reçoivent un événement de mise à jour. Le numéro du dialogue est repris par le suivant. NeoBASIC n'a pas de mot-clé pour cet appel.

Texte de la documentation du firmware (anglais)

Closes dialog Parameter:0 : its window and controls are disposed, the windows it covered get an update.

C (llvm-mos)
/* Fermer un dialogue (groupe 37, 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)
        ;
}

/* Descripteur de dialogue, lu sur place : Rect de la fenêtre (écran), options (bit 0 barre de titre), titre ;
   puis chaque élément : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ de texte, 6 texte fixe), options
   (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation : Échap), Rect relatif au contenu, maximum,
   texte précédé de sa longueur (un champ de texte réserve 1 + maximum octets) ; un 0 termine la liste. */
#define W(v) (v) & 0xFF, (v) >> 8
static uint8_t reglages[] = {
    W(40), W(40), W(240), W(160), 1, 8, 'R', 'e', 'g', 'l', 'a', 'g', 'e', 's',
    1, 2, W(130), W(90), W(190), W(104), W(0), 2, 'O', 'K',                          /* 1 : bouton par défaut */
    1, 4, W(60), W(90), W(120), W(104), W(0), 7, 'A', 'n', 'n', 'u', 'l', 'e', 'r',   /* 2 : annulation */
    2, 0, W(10), W(10), W(100), W(22), W(0), 3, 'S', 'o', 'n',                 /* 3 : case à cocher */
    5, 0, W(10), W(30), W(150), W(44), W(8), 2, 'a', 'b', 0, 0, 0, 0, 0, 0,      /* 4 : champ de texte, 8 au plus */
    6, 0, W(10), W(50), W(150), W(60), W(0), 7, 'B', 'o', 'n', 'j', 'o', 'u', 'r',   /* 5 : texte fixe */
    0 };
#define CHAMP 81                                /* position du tampon de l'élément 4 dans le descripteur */

static void p16(uint8_t i, uint16_t v) {        /* paramètre 16 bits en Pi, Pi+1 */
    ControlPort.params[i] = v & 0xFF;
    ControlPort.params[i + 1] = v >> 8;
}
static void reinit(void) {                      /* 32,19 Toolbox Reset */
    libre();
    api(32, 19);
}
static uint8_t dialogue, fenetre;
static uint8_t ouvrir(uint8_t *descripteur) {   /* 37,1 New Dialog : rend l'indicateur d'erreur */
    libre();
    p16(0, (uint16_t)descripteur);
    api(37, 1);
    dialogue = ControlPort.params[2];
    fenetre = ControlPort.params[3];
    return ControlPort.error;
}
static void fermer(uint8_t d) {                 /* 37,2 Dispose Dialog */
    libre();
    ControlPort.params[0] = d;
    api(37, 2);
}

int main(void) {
    uint8_t avant, apres, n;
    reinit();
    ouvrir(reglages);
    libre(); api(34, 10); avant = ControlPort.params[0];   /* 34,10 : fenêtre de devant */
    fermer(dialogue);                           /* sa fenêtre et ses contrôles sont supprimés */
    libre(); api(34, 10); apres = ControlPort.params[0];
    ouvrir(reglages);
    n = dialogue;
    reinit();
    printf("Fenetre devant : %u, puis %u ; nouveau dialogue : %u\n", avant, apres, n);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Fenetre devant : 1, puis 0 ; nouveau dialogue : 1
Mad Pascal
// Fermer un dialogue (groupe 37, fonction 2, Trinity).
program dl2;
uses crt, neo6502;
// Descripteur de dialogue (variable : le firmware écrit dans le champ de texte), lu sur place : Rect de la
// fenêtre (écran), options (bit 0 barre de titre), titre ; puis chaque élément : type (1 bouton, 2 case, 3 radio,
// 4 barre, 5 champ de texte, 6 texte fixe), options (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation :
// Échap), Rect relatif au contenu, maximum, texte précédé de sa longueur (un champ de texte réserve 1 + maximum
// octets) ; un 0 termine la liste.
var reglages: array[0..110] of byte = (
    40, 0, 40, 0, 240, 0, 160, 0, 1, 8, ord('R'), ord('e'), ord('g'), ord('l'), ord('a'), ord('g'), ord('e'), ord('s'),
    1, 2, 130, 0, 90, 0, 190, 0, 104, 0, 0, 0, 2, ord('O'), ord('K'),   // 1 : bouton par défaut
    1, 4, 60, 0, 90, 0, 120, 0, 104, 0, 0, 0, 7, ord('A'), ord('n'), ord('n'), ord('u'), ord('l'), ord('e'), ord('r'),   // 2 : annulation
    2, 0, 10, 0, 10, 0, 100, 0, 22, 0, 0, 0, 3, ord('S'), ord('o'), ord('n'),   // 3 : case à cocher
    5, 0, 10, 0, 30, 0, 150, 0, 44, 0, 8, 0, 2, ord('a'), ord('b'), 0, 0, 0, 0, 0, 0,   // 4 : champ de texte, 8 au plus
    6, 0, 10, 0, 50, 0, 150, 0, 60, 0, 0, 0, 7, ord('B'), ord('o'), ord('n'), ord('j'), ord('o'), ord('u'), ord('r'),   // 5 : texte fixe
    0);
const CHAMP = 81;                               // position du tampon de l'élément 4 dans le descripteur

var dialogue, fenetre: byte;

procedure appel(g, f: byte);                    // appel g,f (paramètres déjà posés)
begin
  NeoSendMessage(g, f);
  NeoWaitMessage;
end;

procedure reinit;                               // 32,19 Toolbox Reset
begin
  NeoWaitMessage;
  appel(32, 19);
end;

function ouvrir(descripteur: pointer): byte;    // 37,1 New Dialog : rend l'indicateur d'erreur
begin
  NeoWaitMessage;
  wordParams[0] := word(descripteur);
  appel(37, 1);
  dialogue := NeoMessage.params[2];
  fenetre := NeoMessage.params[3];
  result := NeoMessage.error;
end;

procedure fermer(d: byte);                      // 37,2 Dispose Dialog
begin
  NeoWaitMessage;
  NeoMessage.params[0] := d;
  appel(37, 2);
end;

var avant, apres, n: byte;
begin
  reinit;
  ouvrir(@reglages);
  NeoWaitMessage; appel(34, 10); avant := NeoMessage.params[0];   // 34,10 : fenêtre de devant
  fermer(dialogue);                             // sa fenêtre et ses contrôles sont supprimés
  appel(34, 10); apres := NeoMessage.params[0];
  ouvrir(@reglages);
  n := dialogue;
  reinit;
  writeln('Fenetre devant : ', avant, ', puis ', apres, ' ; nouveau dialogue : ', n);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Fenetre devant : 1, puis 0 ; nouveau dialogue : 1
NeoBASIC
10 ' Fermer un dialogue (groupe 37, fonction 2, Trinity)
15 gosub 7000
20 gosub 8300
30 q = rg : gosub 8000
40 gosub 2000 : av = dv : ' 34,10 : fenetre de devant
50 gosub 8200 : ' sa fenetre et ses controles sont supprimes
60 gosub 2000 : ap = dv
70 gosub 8000 : n = dg
80 gosub 8300
90 print "Fenetre devant : ";av;", puis ";ap;" ; nouveau dialogue : ";n
100 end
2000 while peek($ff00) : wend : poke $ff01, 10 : poke $ff00, 34
2010 while peek($ff00) : wend : dv = peek($ff04) : return
7000 ' descripteur de dialogue, lu sur place : Rect de la fenetre (ecran), options (bit 0 barre de titre), titre ;
7005 ' puis chaque element : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ, 6 texte fixe), options (bit 0 inactif,
7010 ' bit 1 par defaut : Entree, bit 2 annulation : Echap), Rect relatif au contenu, maximum, texte precede de sa
7015 ' longueur (un champ de texte reserve 1 + maximum octets) ; un 0 termine la liste. Adresse dans rg.
7020 rg = alloc(111) : p = rg
7025 for k = 1 to 4 : read v : doke p, v : p = p + 2 : next k : read v : poke p, v : p = p + 1 : read s$ : gosub 7100
7030 for it = 1 to 5 : read ty, op : poke p, ty : poke p + 1, op : p = p + 2
7035 for k = 1 to 5 : read v : doke p, v : p = p + 2 : next k : read s$ : p0 = p : gosub 7100
7040 if ty = 5 then p = p0 + 1 + v : ' le champ reserve 1 + maximum octets
7045 next it : poke p, 0 : ch = rg + 81 : return : ' ch : tampon de l'element 4
7050 data 40, 40, 240, 160, 1, "Reglages"
7055 data 1, 2, 130, 90, 190, 104, 0, "OK" : ' 1 : bouton par defaut
7060 data 1, 4, 60, 90, 120, 104, 0, "Annuler" : ' 2 : annulation
7065 data 2, 0, 10, 10, 100, 22, 0, "Son" : ' 3 : case a cocher
7070 data 5, 0, 10, 30, 150, 44, 8, "ab" : ' 4 : champ de texte, 8 au plus
7075 data 6, 0, 10, 50, 150, 60, 0, "Bonjour" : ' 5 : texte fixe
7100 poke p, len(s$) : for i = 1 to len(s$) : poke p + i, asc(mid$(s$, i, 1)) : next i : p = p + len(s$) + 1 : return
8000 ' 37,1 New Dialog sur le descripteur q : dialogue dans dg, fenetre dans fw, erreur dans e
8010 while peek($ff00) : wend : doke $ff04, q : f = 1 : gosub 8110
8020 dg = peek($ff06) : fw = peek($ff07) : return
8100 ' appel 37,f, parametres deja poses ; erreur dans e
8110 poke $ff01, f : poke $ff00, 37
8120 while peek($ff00) : wend : e = peek($ff02) : return
8200 ' 37,2 Dispose Dialog dg
8210 while peek($ff00) : wend : poke $ff04, dg : f = 2 : goto 8110
8300 ' 32,19 Toolbox Reset
8310 while peek($ff00) : wend : poke $ff01, 19 : poke $ff00, 32
8320 while peek($ff00) : wend : return
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Fenetre devant : 1, puis 0 ; nouveau dialogue : 1
Assembleur 65C02 (64tass)
; Fermer un dialogue (groupe 37, 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 #<b0
        ldx #>b0
        jsr envoi
        jsr ouvrir
        jsr WaitMessage
        lda #34
        ldx #10                    ; 34,10 : fenêtre de devant
        jsr appel
        lda ControlPort+4
        sta av
        lda dlg
        ldx #2                     ; Dispose Dialog : sa fenêtre et ses contrôles sont supprimés
        jsr dial
        jsr WaitMessage
        lda #34
        ldx #10                    ; 34,10 : fenêtre de devant
        jsr appel
        lda ControlPort+4
        sta ap
        jsr ouvrir
        lda dlg
        sta n
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda av
        jsr decimal
        lda #<t3
        ldx #>t3
        jsr ecrire
        lda ap
        jsr decimal
        lda #<t4
        ldx #>t4
        jsr ecrire
        lda n
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Descripteur de dialogue, lu sur place : Rect de la fenêtre (écran), options (bit 0 barre de titre), titre ;
; puis chaque élément : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ de texte, 6 texte fixe), options
; (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation : Échap), Rect relatif au contenu, maximum,
; texte précédé de sa longueur (un champ de texte réserve 1 + maximum octets) ; un 0 termine la liste.
reglages: .word 40, 40, 240, 160
        .byte 1, 8
        .text "Reglages"
type1:  .byte 1, 2                 ; 1 : bouton par défaut
        .word 130, 90, 190, 104, 0
        .byte 2
        .text "OK"
        .byte 1, 4                 ; 2 : annulation
        .word 60, 90, 120, 104, 0
        .byte 7
        .text "Annuler"
        .byte 2, 0                 ; 3 : case à cocher
        .word 10, 10, 100, 22, 0
        .byte 3
        .text "Son"
        .byte 5, 0                 ; 4 : champ de texte, 8 au plus
        .word 10, 30, 150, 44, 8
champ:  .byte 2
        .text "ab"
        .fill 6
        .byte 6, 0                 ; 5 : texte fixe
        .word 10, 50, 150, 60, 0
        .byte 7
        .text "Bonjour"
        .byte 0
b0:     .byte 32, 19, 0            ; 32,19 Toolbox Reset
av:     .byte 0
ap:     .byte 0
n:      .byte 0
b1:     .byte 32, 19, 0            ; 32,19 Toolbox Reset
t2:     .text "Fenetre devant : ", 0
t3:     .text ", puis ", 0
t4:     .text " ; nouveau dialogue : ", 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

; 37,1 New Dialog sur le descripteur reglages : dialogue dans dlg, fenêtre dans fen ; erreur dans A.
ouvrir: jsr WaitMessage
        lda #<reglages
        sta ControlPort+4
        lda #>reglages
        sta ControlPort+5
        lda #37
        ldx #1
        jsr appel
        lda ControlPort+6
        sta dlg
        lda ControlPort+7
        sta fen
        lda ControlPort+2
        rts

; 37,X sur le dialogue A.
dial:   pha
        phx
        jsr WaitMessage
        plx
        pla
        sta ControlPort+4
        lda #37
        jmp appel

dlg:    .byte 0
fen:    .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
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Fenetre devant : 1, puis 0 ; nouveau dialogue : 1

37,3 Dialog Event Trinity

Passe un événement (groupe 33) au dialogue et rend l'élément qui a agi.

Entrées
OctetsTypeRôle
P0uint8numéro du dialogue
P1-P2addradresse de l'EventRecord
Sorties
OctetsTypeRôle
P3uint8élément qui a agi (1, 2... dans l'ordre du descripteur), 0 si aucun
P4uint81 si l'événement appartenait au dialogue

Un élément agit quand : un bouton est relâché dedans, Entrée (élément par défaut), Échap (élément d'annulation), une case bascule, une barre bouge, un champ de texte est cliqué ou modifié. Pendant que le dialogue est ouvert, tous les événements de souris et de clavier lui appartiennent, même un clic hors de sa fenêtre (relevé au banc) ; les mises à jour d'autres fenêtres et les minuteurs restent au programme. L'exemple fabrique ses événements ; un programme passe ceux de 33,2 jusqu'à obtenir l'élément attendu, puis appelle 37,2. NeoBASIC n'a pas de mot-clé pour cet appel.

Texte de la documentation du firmware (anglais)

Gives dialog Parameter:0 the EventRecord (group 33) at Parameters:1,2. Returns in Parameter:3 the item that acted (1.. in descriptor order, 0 none) : a button released inside it, the default item on Return, the cancel item on Escape, a box toggled, a scroll bar moved, a text field clicked or edited ; and in Parameter:4 whether the event belonged to the dialog (1 : every mouse and key event while it is up, its own update - redrawn here - and activate events ; 0 : update/activate of other windows, timers, which the program still handles). The program keeps calling this for every event until it gets the item it waits for, then Dispose Dialog.

C (llvm-mos)
/* Passer un événement au dialogue (groupe 37, 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)
        ;
}

/* Descripteur de dialogue, lu sur place : Rect de la fenêtre (écran), options (bit 0 barre de titre), titre ;
   puis chaque élément : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ de texte, 6 texte fixe), options
   (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation : Échap), Rect relatif au contenu, maximum,
   texte précédé de sa longueur (un champ de texte réserve 1 + maximum octets) ; un 0 termine la liste. */
#define W(v) (v) & 0xFF, (v) >> 8
static uint8_t reglages[] = {
    W(40), W(40), W(240), W(160), 1, 8, 'R', 'e', 'g', 'l', 'a', 'g', 'e', 's',
    1, 2, W(130), W(90), W(190), W(104), W(0), 2, 'O', 'K',                          /* 1 : bouton par défaut */
    1, 4, W(60), W(90), W(120), W(104), W(0), 7, 'A', 'n', 'n', 'u', 'l', 'e', 'r',   /* 2 : annulation */
    2, 0, W(10), W(10), W(100), W(22), W(0), 3, 'S', 'o', 'n',                 /* 3 : case à cocher */
    5, 0, W(10), W(30), W(150), W(44), W(8), 2, 'a', 'b', 0, 0, 0, 0, 0, 0,      /* 4 : champ de texte, 8 au plus */
    6, 0, W(10), W(50), W(150), W(60), W(0), 7, 'B', 'o', 'n', 'j', 'o', 'u', 'r',   /* 5 : texte fixe */
    0 };
#define CHAMP 81                                /* position du tampon de l'élément 4 dans le descripteur */

static void p16(uint8_t i, uint16_t v) {        /* paramètre 16 bits en Pi, Pi+1 */
    ControlPort.params[i] = v & 0xFF;
    ControlPort.params[i + 1] = v >> 8;
}
static void reinit(void) {                      /* 32,19 Toolbox Reset */
    libre();
    api(32, 19);
}
static uint8_t dialogue, fenetre;
static uint8_t ouvrir(uint8_t *descripteur) {   /* 37,1 New Dialog : rend l'indicateur d'erreur */
    libre();
    p16(0, (uint16_t)descripteur);
    api(37, 1);
    dialogue = ControlPort.params[2];
    fenetre = ControlPort.params[3];
    return ControlPort.error;
}
static void fermer(uint8_t d) {                 /* 37,2 Dispose Dialog */
    libre();
    ControlPort.params[0] = d;
    api(37, 2);
}

/* Événements fabriqués comme ceux du groupe 33 : type, message, message2, modificateurs, X, Y. */
typedef struct { uint8_t what, message, message2, modifiers; int16_t x, y; } EventRecord;
static EventRecord ev;
static uint8_t a_lui;
static uint8_t evenement(uint8_t d, uint8_t what, uint8_t m, uint8_t m2, int16_t x, int16_t y) {   /* 37,3 Dialog Event */
    ev.what = what; ev.message = m; ev.message2 = m2; ev.modifiers = 0; ev.x = x; ev.y = y;
    libre();
    ControlPort.params[0] = d;
    p16(1, (uint16_t)&ev);
    api(37, 3);
    a_lui = ControlPort.params[4];              /* 1 si l'événement appartenait au dialogue */
    return ControlPort.params[3];               /* élément qui a agi, 0 si aucun */
}

int main(void) {
    uint8_t x, t, ent, ech, son, tim, ta, i;
    reinit();
    ouvrir(reglages);
    x = evenement(dialogue, 1, 'X', 0x1B, 0, 0);    /* touche « X » : au champ de texte */
    t = reglages[CHAMP];
    son = evenement(dialogue, 4, 1, 1, 60, 65); /* clic sur la case « Son », en (51, 61) à l'écran */
    son = evenement(dialogue, 5, 0, 1, 60, 65); /* elle agit au relâchement */
    ent = evenement(dialogue, 1, 13, 0x28, 0, 0);   /* Entrée : le bouton par défaut */
    ech = evenement(dialogue, 1, 27, 0x29, 0, 0);   /* Échap : le bouton d'annulation */
    tim = evenement(dialogue, 8, 0, 0, 0, 0);   /* minuteur : pas pour le dialogue */
    ta = a_lui;
    reinit();
    printf("X : element %u, champ : ", x);
    for (i = 1; i <= t; i++)
        putchar(reglages[CHAMP + i]);
    printf("\nSon : %u, Entree : %u, Echap : %u\nMinuteur : %u, au dialogue : %u\n", son, ent, ech, tim, ta);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
X : element 4, champ : abX
Son : 3, Entree : 1, Echap : 2
Minuteur : 0, au dialogue : 0
Mad Pascal
// Passer un événement au dialogue (groupe 37, fonction 3, Trinity).
program dl3;
uses crt, neo6502;
// Descripteur de dialogue (variable : le firmware écrit dans le champ de texte), lu sur place : Rect de la
// fenêtre (écran), options (bit 0 barre de titre), titre ; puis chaque élément : type (1 bouton, 2 case, 3 radio,
// 4 barre, 5 champ de texte, 6 texte fixe), options (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation :
// Échap), Rect relatif au contenu, maximum, texte précédé de sa longueur (un champ de texte réserve 1 + maximum
// octets) ; un 0 termine la liste.
var reglages: array[0..110] of byte = (
    40, 0, 40, 0, 240, 0, 160, 0, 1, 8, ord('R'), ord('e'), ord('g'), ord('l'), ord('a'), ord('g'), ord('e'), ord('s'),
    1, 2, 130, 0, 90, 0, 190, 0, 104, 0, 0, 0, 2, ord('O'), ord('K'),   // 1 : bouton par défaut
    1, 4, 60, 0, 90, 0, 120, 0, 104, 0, 0, 0, 7, ord('A'), ord('n'), ord('n'), ord('u'), ord('l'), ord('e'), ord('r'),   // 2 : annulation
    2, 0, 10, 0, 10, 0, 100, 0, 22, 0, 0, 0, 3, ord('S'), ord('o'), ord('n'),   // 3 : case à cocher
    5, 0, 10, 0, 30, 0, 150, 0, 44, 0, 8, 0, 2, ord('a'), ord('b'), 0, 0, 0, 0, 0, 0,   // 4 : champ de texte, 8 au plus
    6, 0, 10, 0, 50, 0, 150, 0, 60, 0, 0, 0, 7, ord('B'), ord('o'), ord('n'), ord('j'), ord('o'), ord('u'), ord('r'),   // 5 : texte fixe
    0);
const CHAMP = 81;                               // position du tampon de l'élément 4 dans le descripteur

var dialogue, fenetre: byte;

procedure appel(g, f: byte);                    // appel g,f (paramètres déjà posés)
begin
  NeoSendMessage(g, f);
  NeoWaitMessage;
end;

procedure reinit;                               // 32,19 Toolbox Reset
begin
  NeoWaitMessage;
  appel(32, 19);
end;

function ouvrir(descripteur: pointer): byte;    // 37,1 New Dialog : rend l'indicateur d'erreur
begin
  NeoWaitMessage;
  wordParams[0] := word(descripteur);
  appel(37, 1);
  dialogue := NeoMessage.params[2];
  fenetre := NeoMessage.params[3];
  result := NeoMessage.error;
end;

procedure fermer(d: byte);                      // 37,2 Dispose Dialog
begin
  NeoWaitMessage;
  NeoMessage.params[0] := d;
  appel(37, 2);
end;

// Événements fabriqués comme ceux du groupe 33 : type, message, message2, modificateurs, X, Y.
type EventRecord = record what, message, message2, modifiers: byte; x, y: smallint; end;
var ev: EventRecord;
    a_lui: byte;

function evenement(d, what, m, m2: byte; x, y: smallint): byte;   // 37,3 Dialog Event
begin
  ev.what := what; ev.message := m; ev.message2 := m2; ev.modifiers := 0; ev.x := x; ev.y := y;
  NeoWaitMessage;
  NeoMessage.params[0] := d;
  NeoMessage.params[1] := lo(word(@ev));
  NeoMessage.params[2] := hi(word(@ev));
  appel(37, 3);
  a_lui := NeoMessage.params[4];                // 1 si l'événement appartenait au dialogue
  result := NeoMessage.params[3];               // élément qui a agi, 0 si aucun
end;

var x, t, ent, ech, son, tim, ta, i: byte;
begin
  reinit;
  ouvrir(@reglages);
  x := evenement(dialogue, 1, ord('X'), $1B, 0, 0);   // touche « X » : au champ de texte
  t := reglages[CHAMP];
  evenement(dialogue, 4, 1, 1, 60, 65);         // clic sur la case « Son », en (51, 61) à l'écran
  son := evenement(dialogue, 5, 0, 1, 60, 65);  // elle agit au relâchement
  ent := evenement(dialogue, 1, 13, $28, 0, 0);    // Entrée : le bouton par défaut
  ech := evenement(dialogue, 1, 27, $29, 0, 0);    // Échap : le bouton d'annulation
  tim := evenement(dialogue, 8, 0, 0, 0, 0);    // minuteur : pas pour le dialogue
  ta := a_lui;
  reinit;
  write('X : element ', x, ', champ : ');
  for i := 1 to t do write(chr(reglages[CHAMP + i]));
  writeln;
  writeln('Son : ', son, ', Entree : ', ent, ', Echap : ', ech);
  writeln('Minuteur : ', tim, ', au dialogue : ', ta);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
X : element 4, champ : abX
Son : 3, Entree : 1, Echap : 2
Minuteur : 0, au dialogue : 0
NeoBASIC
10 ' Passer un evenement au dialogue (groupe 37, fonction 3, Trinity)
15 gosub 7000
20 ev = alloc(8) : ' evenements fabriques comme ceux du groupe 33 : type, message, message2, modificateurs, X, Y
30 gosub 8300
40 q = rg : gosub 8000
50 wh = 1 : ms = asc("X") : m2 = $1b : ex = 0 : ey = 0 : gosub 7500 : x = it : ' touche « X » : au champ de texte
60 wh = 4 : ms = 1 : m2 = 1 : ex = 60 : ey = 65 : gosub 7500 : ' clic sur la case « Son », en (51, 61) a l'ecran
70 wh = 5 : ms = 0 : gosub 7500 : so = it : ' elle agit au relachement
80 wh = 1 : ms = 13 : m2 = $28 : ex = 0 : ey = 0 : gosub 7500 : en = it : ' Entree : le bouton par defaut
90 ms = 27 : m2 = $29 : gosub 7500 : ec = it : ' Echap : le bouton d'annulation
100 wh = 8 : ms = 0 : m2 = 0 : gosub 7500 : ti = it : ta = al : ' minuteur : pas pour le dialogue
110 gosub 8300
120 print "X : element ";x;", champ : "; : for i = 1 to peek(ch) : print chr$(peek(ch + i)); : next i : print
130 print "Son : ";so;", Entree : ";en;", Echap : ";ec
140 print "Minuteur : ";ti;", au dialogue : ";ta
150 end
7500 ' 37,3 Dialog Event : evenement fabrique (type wh, message ms, message2 m2, X ex, Y ey) pour le dialogue dg
7510 ' element qui a agi dans it (0 si aucun), al = 1 si l'evenement appartenait au dialogue
7520 poke ev, wh : poke ev + 1, ms : poke ev + 2, m2 : poke ev + 3, 0 : doke ev + 4, ex : doke ev + 6, ey
7530 while peek($ff00) : wend : poke $ff04, dg : doke $ff05, ev : f = 3 : gosub 8110
7540 it = peek($ff07) : al = peek($ff08) : return
7000 ' descripteur de dialogue, lu sur place : Rect de la fenetre (ecran), options (bit 0 barre de titre), titre ;
7005 ' puis chaque element : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ, 6 texte fixe), options (bit 0 inactif,
7010 ' bit 1 par defaut : Entree, bit 2 annulation : Echap), Rect relatif au contenu, maximum, texte precede de sa
7015 ' longueur (un champ de texte reserve 1 + maximum octets) ; un 0 termine la liste. Adresse dans rg.
7020 rg = alloc(111) : p = rg
7025 for k = 1 to 4 : read v : doke p, v : p = p + 2 : next k : read v : poke p, v : p = p + 1 : read s$ : gosub 7100
7030 for it = 1 to 5 : read ty, op : poke p, ty : poke p + 1, op : p = p + 2
7035 for k = 1 to 5 : read v : doke p, v : p = p + 2 : next k : read s$ : p0 = p : gosub 7100
7040 if ty = 5 then p = p0 + 1 + v : ' le champ reserve 1 + maximum octets
7045 next it : poke p, 0 : ch = rg + 81 : return : ' ch : tampon de l'element 4
7050 data 40, 40, 240, 160, 1, "Reglages"
7055 data 1, 2, 130, 90, 190, 104, 0, "OK" : ' 1 : bouton par defaut
7060 data 1, 4, 60, 90, 120, 104, 0, "Annuler" : ' 2 : annulation
7065 data 2, 0, 10, 10, 100, 22, 0, "Son" : ' 3 : case a cocher
7070 data 5, 0, 10, 30, 150, 44, 8, "ab" : ' 4 : champ de texte, 8 au plus
7075 data 6, 0, 10, 50, 150, 60, 0, "Bonjour" : ' 5 : texte fixe
7100 poke p, len(s$) : for i = 1 to len(s$) : poke p + i, asc(mid$(s$, i, 1)) : next i : p = p + len(s$) + 1 : return
8000 ' 37,1 New Dialog sur le descripteur q : dialogue dans dg, fenetre dans fw, erreur dans e
8010 while peek($ff00) : wend : doke $ff04, q : f = 1 : gosub 8110
8020 dg = peek($ff06) : fw = peek($ff07) : return
8100 ' appel 37,f, parametres deja poses ; erreur dans e
8110 poke $ff01, f : poke $ff00, 37
8120 while peek($ff00) : wend : e = peek($ff02) : return
8200 ' 37,2 Dispose Dialog dg
8210 while peek($ff00) : wend : poke $ff04, dg : f = 2 : goto 8110
8300 ' 32,19 Toolbox Reset
8310 while peek($ff00) : wend : poke $ff01, 19 : poke $ff00, 32
8320 while peek($ff00) : wend : return
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
X : element 4, champ : abX
Son : 3, Entree : 1, Echap : 2
Minuteur : 0, au dialogue : 0
Assembleur 65C02 (64tass)
; Passer un événement au dialogue (groupe 37, 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
        jsr ouvrir
        lda #1
        sta ev
        lda #'X'
        sta ev+1
        lda #$1B
        sta ev+2
        lda #0
        sta ev+4
        lda #0                  ; touche « X » : au champ de texte
        sta ev+6
        lda dlg
        jsr evenement
        sta x
        lda #4
        sta ev
        lda #1
        sta ev+1
        lda #1
        sta ev+2
        lda #60
        sta ev+4
        lda #65                 ; clic sur la case « Son », en (51, 61) à l'écran
        sta ev+6
        lda dlg
        jsr evenement
        lda #5
        sta ev
        lda #0
        sta ev+1
        lda #1
        sta ev+2
        lda #60
        sta ev+4
        lda #65                 ; elle agit au relâchement
        sta ev+6
        lda dlg
        jsr evenement
        sta so
        lda #1
        sta ev
        lda #13
        sta ev+1
        lda #$28
        sta ev+2
        lda #0
        sta ev+4
        lda #0                  ; Entrée : le bouton par défaut
        sta ev+6
        lda dlg
        jsr evenement
        sta en
        lda #1
        sta ev
        lda #27
        sta ev+1
        lda #$29
        sta ev+2
        lda #0
        sta ev+4
        lda #0                  ; Échap : le bouton d'annulation
        sta ev+6
        lda dlg
        jsr evenement
        sta ec
        lda #8
        sta ev
        lda #0
        sta ev+1
        lda #0
        sta ev+2
        lda #0
        sta ev+4
        lda #0                  ; minuteur : pas pour le dialogue
        sta ev+6
        lda dlg
        jsr evenement
        sta ti
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda x
        jsr decimal
        lda #<t3
        ldx #>t3
        jsr ecrire
        ldx #0
_ch:    cpx champ
        beq _hc
        lda champ+1,x
        jsr WriteCharacter
        inx
        bra _ch
_hc:    lda #13
        jsr WriteCharacter
        lda #<t4
        ldx #>t4
        jsr ecrire
        lda so
        jsr decimal
        lda #<t5
        ldx #>t5
        jsr ecrire
        lda en
        jsr decimal
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda ec
        jsr decimal
        lda #13
        jsr WriteCharacter
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda ti
        jsr decimal
        lda #<t8
        ldx #>t8
        jsr ecrire
        lda alui
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Descripteur de dialogue, lu sur place : Rect de la fenêtre (écran), options (bit 0 barre de titre), titre ;
; puis chaque élément : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ de texte, 6 texte fixe), options
; (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation : Échap), Rect relatif au contenu, maximum,
; texte précédé de sa longueur (un champ de texte réserve 1 + maximum octets) ; un 0 termine la liste.
reglages: .word 40, 40, 240, 160
        .byte 1, 8
        .text "Reglages"
type1:  .byte 1, 2                 ; 1 : bouton par défaut
        .word 130, 90, 190, 104, 0
        .byte 2
        .text "OK"
        .byte 1, 4                 ; 2 : annulation
        .word 60, 90, 120, 104, 0
        .byte 7
        .text "Annuler"
        .byte 2, 0                 ; 3 : case à cocher
        .word 10, 10, 100, 22, 0
        .byte 3
        .text "Son"
        .byte 5, 0                 ; 4 : champ de texte, 8 au plus
        .word 10, 30, 150, 44, 8
champ:  .byte 2
        .text "ab"
        .fill 6
        .byte 6, 0                 ; 5 : texte fixe
        .word 10, 50, 150, 60, 0
        .byte 7
        .text "Bonjour"
        .byte 0
b0:     .byte 32, 19, 0            ; 32,19 Toolbox Reset
x:      .byte 0
so:     .byte 0
en:     .byte 0
ec:     .byte 0
ti:     .byte 0
b1:     .byte 32, 19, 0            ; 32,19 Toolbox Reset
t2:     .text "X : element ", 0
t3:     .text ", champ : ", 0
t4:     .text "Son : ", 0
t5:     .text ", Entree : ", 0
t6:     .text ", Echap : ", 0
t7:     .text "Minuteur : ", 0
t8:     .text ", au dialogue : ", 0

; 37,3 Dialog Event : l'événement ev (fabriqué comme ceux du groupe 33 : type, message, message2,
; modificateurs, X, Y) pour le dialogue A ; élément qui a agi dans A (0 si aucun), appartenance dans alui.
evenement:
        pha
        jsr WaitMessage
        pla
        sta ControlPort+4
        lda #<ev
        sta ControlPort+5
        lda #>ev
        sta ControlPort+6
        lda #37
        ldx #3
        jsr appel
        lda ControlPort+8          ; 1 si l'événement appartenait au dialogue
        sta alui
        lda ControlPort+7          ; élément qui a agi
        rts
ev:     .byte 0, 0, 0, 0
        .word 0, 0
alui:   .byte 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

; 37,1 New Dialog sur le descripteur reglages : dialogue dans dlg, fenêtre dans fen ; erreur dans A.
ouvrir: jsr WaitMessage
        lda #<reglages
        sta ControlPort+4
        lda #>reglages
        sta ControlPort+5
        lda #37
        ldx #1
        jsr appel
        lda ControlPort+6
        sta dlg
        lda ControlPort+7
        sta fen
        lda ControlPort+2
        rts

; 37,X sur le dialogue A.
dial:   pha
        phx
        jsr WaitMessage
        plx
        pla
        sta ControlPort+4
        lda #37
        jmp appel

dlg:    .byte 0
fen:    .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
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
X : element 4, champ : abX
Son : 3, Entree : 1, Echap : 2
Minuteur : 0, au dialogue : 0

37,4 Get Dialog Item Trinity

Rend le contrôle (groupe 36) et le type d'un élément du dialogue.

Entrées
OctetsTypeRôle
P0uint8numéro du dialogue
P1uint8numéro de l'élément (1, 2...)
Sorties
OctetsTypeRôle
P2uint8contrôle du groupe 36 (0 pour un texte fixe)
P3uint8type de l'élément

Le contrôle se pilote ensuite avec le groupe 36 : l'exemple coche la case avec 36,5 et la relit avec 36,6. NeoBASIC n'a pas de mot-clé pour cet appel.

Texte de la documentation du firmware (anglais)

Returns in Parameter:2 the control (group 36 : Set/Get Control Value, Set Control Flags) behind item Parameter:1 of dialog Parameter:0 (0 for static text) and its kind in Parameter:3.

C (llvm-mos)
/* Lire le contrôle d'un élément (groupe 37, 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)
        ;
}

/* Descripteur de dialogue, lu sur place : Rect de la fenêtre (écran), options (bit 0 barre de titre), titre ;
   puis chaque élément : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ de texte, 6 texte fixe), options
   (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation : Échap), Rect relatif au contenu, maximum,
   texte précédé de sa longueur (un champ de texte réserve 1 + maximum octets) ; un 0 termine la liste. */
#define W(v) (v) & 0xFF, (v) >> 8
static uint8_t reglages[] = {
    W(40), W(40), W(240), W(160), 1, 8, 'R', 'e', 'g', 'l', 'a', 'g', 'e', 's',
    1, 2, W(130), W(90), W(190), W(104), W(0), 2, 'O', 'K',                          /* 1 : bouton par défaut */
    1, 4, W(60), W(90), W(120), W(104), W(0), 7, 'A', 'n', 'n', 'u', 'l', 'e', 'r',   /* 2 : annulation */
    2, 0, W(10), W(10), W(100), W(22), W(0), 3, 'S', 'o', 'n',                 /* 3 : case à cocher */
    5, 0, W(10), W(30), W(150), W(44), W(8), 2, 'a', 'b', 0, 0, 0, 0, 0, 0,      /* 4 : champ de texte, 8 au plus */
    6, 0, W(10), W(50), W(150), W(60), W(0), 7, 'B', 'o', 'n', 'j', 'o', 'u', 'r',   /* 5 : texte fixe */
    0 };
#define CHAMP 81                                /* position du tampon de l'élément 4 dans le descripteur */

static void p16(uint8_t i, uint16_t v) {        /* paramètre 16 bits en Pi, Pi+1 */
    ControlPort.params[i] = v & 0xFF;
    ControlPort.params[i + 1] = v >> 8;
}
static void reinit(void) {                      /* 32,19 Toolbox Reset */
    libre();
    api(32, 19);
}
static uint8_t dialogue, fenetre;
static uint8_t ouvrir(uint8_t *descripteur) {   /* 37,1 New Dialog : rend l'indicateur d'erreur */
    libre();
    p16(0, (uint16_t)descripteur);
    api(37, 1);
    dialogue = ControlPort.params[2];
    fenetre = ControlPort.params[3];
    return ControlPort.error;
}
static void fermer(uint8_t d) {                 /* 37,2 Dispose Dialog */
    libre();
    ControlPort.params[0] = d;
    api(37, 2);
}

int main(void) {
    uint8_t c[5], t[5], i;
    uint8_t v;
    reinit();
    ouvrir(reglages);
    for (i = 0; i < 5; i++) {
        libre();
        ControlPort.params[0] = dialogue;
        ControlPort.params[1] = i + 1;
        api(37, 4);                             /* Get Dialog Item */
        c[i] = ControlPort.params[2];           /* contrôle du groupe 36, 0 pour un texte fixe */
        t[i] = ControlPort.params[3];           /* type */
    }
    libre(); ControlPort.params[0] = c[2]; p16(1, 1); api(36, 5);   /* 36,5 : coche la case */
    libre(); ControlPort.params[0] = c[2]; api(36, 6);
    v = ControlPort.params[1];
    reinit();
    printf("Elements :");
    for (i = 0; i < 5; i++)
        printf(" %u/%u", c[i], t[i]);
    printf("\nCase cochee par 36,5 : %u\n", v);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Elements : 1/1 2/1 3/2 4/5 0/6
Case cochee par 36,5 : 1
Mad Pascal
// Lire le contrôle d'un élément (groupe 37, fonction 4, Trinity).
program dl4;
uses crt, neo6502;
// Descripteur de dialogue (variable : le firmware écrit dans le champ de texte), lu sur place : Rect de la
// fenêtre (écran), options (bit 0 barre de titre), titre ; puis chaque élément : type (1 bouton, 2 case, 3 radio,
// 4 barre, 5 champ de texte, 6 texte fixe), options (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation :
// Échap), Rect relatif au contenu, maximum, texte précédé de sa longueur (un champ de texte réserve 1 + maximum
// octets) ; un 0 termine la liste.
var reglages: array[0..110] of byte = (
    40, 0, 40, 0, 240, 0, 160, 0, 1, 8, ord('R'), ord('e'), ord('g'), ord('l'), ord('a'), ord('g'), ord('e'), ord('s'),
    1, 2, 130, 0, 90, 0, 190, 0, 104, 0, 0, 0, 2, ord('O'), ord('K'),   // 1 : bouton par défaut
    1, 4, 60, 0, 90, 0, 120, 0, 104, 0, 0, 0, 7, ord('A'), ord('n'), ord('n'), ord('u'), ord('l'), ord('e'), ord('r'),   // 2 : annulation
    2, 0, 10, 0, 10, 0, 100, 0, 22, 0, 0, 0, 3, ord('S'), ord('o'), ord('n'),   // 3 : case à cocher
    5, 0, 10, 0, 30, 0, 150, 0, 44, 0, 8, 0, 2, ord('a'), ord('b'), 0, 0, 0, 0, 0, 0,   // 4 : champ de texte, 8 au plus
    6, 0, 10, 0, 50, 0, 150, 0, 60, 0, 0, 0, 7, ord('B'), ord('o'), ord('n'), ord('j'), ord('o'), ord('u'), ord('r'),   // 5 : texte fixe
    0);
const CHAMP = 81;                               // position du tampon de l'élément 4 dans le descripteur

var dialogue, fenetre: byte;

procedure appel(g, f: byte);                    // appel g,f (paramètres déjà posés)
begin
  NeoSendMessage(g, f);
  NeoWaitMessage;
end;

procedure reinit;                               // 32,19 Toolbox Reset
begin
  NeoWaitMessage;
  appel(32, 19);
end;

function ouvrir(descripteur: pointer): byte;    // 37,1 New Dialog : rend l'indicateur d'erreur
begin
  NeoWaitMessage;
  wordParams[0] := word(descripteur);
  appel(37, 1);
  dialogue := NeoMessage.params[2];
  fenetre := NeoMessage.params[3];
  result := NeoMessage.error;
end;

procedure fermer(d: byte);                      // 37,2 Dispose Dialog
begin
  NeoWaitMessage;
  NeoMessage.params[0] := d;
  appel(37, 2);
end;

var c, t: array[0..4] of byte;
    i, v: byte;
begin
  reinit;
  ouvrir(@reglages);
  for i := 0 to 4 do begin
    NeoWaitMessage;
    NeoMessage.params[0] := dialogue;
    NeoMessage.params[1] := i + 1;
    appel(37, 4);                               // Get Dialog Item
    c[i] := NeoMessage.params[2];               // contrôle du groupe 36, 0 pour un texte fixe
    t[i] := NeoMessage.params[3];               // type
  end;
  NeoWaitMessage;
  NeoMessage.params[0] := c[2]; NeoMessage.params[1] := 1; NeoMessage.params[2] := 0;
  appel(36, 5);                                 // 36,5 : coche la case
  NeoMessage.params[0] := c[2];
  appel(36, 6);
  v := NeoMessage.params[1];
  reinit;
  write('Elements :');
  for i := 0 to 4 do write(' ', c[i], '/', t[i]);
  writeln;
  writeln('Case cochee par 36,5 : ', v);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Elements : 1/1 2/1 3/2 4/5 0/6
Case cochee par 36,5 : 1
NeoBASIC
10 ' Lire le controle d'un element (groupe 37, fonction 4, Trinity)
15 gosub 7000
20 dim c(4), t(4)
30 gosub 8300
40 q = rg : gosub 8000
50 for k = 0 to 4
60 while peek($ff00) : wend : poke $ff04, dg : poke $ff05, k + 1 : f = 4 : gosub 8110 : ' Get Dialog Item
70 c(k) = peek($ff06) : t(k) = peek($ff07) : next k : ' controle du groupe 36 (0 : texte fixe), type
80 while peek($ff00) : wend : poke $ff04, c(2) : doke $ff05, 1 : poke $ff01, 5 : poke $ff00, 36 : ' 36,5 : coche la case
90 while peek($ff00) : wend : poke $ff04, c(2) : poke $ff01, 6 : poke $ff00, 36
100 while peek($ff00) : wend : v = peek($ff05)
110 gosub 8300
120 print "Elements :"; : for k = 0 to 4 : print " ";c(k);"/";t(k); : next k : print
130 print "Case cochee par 36,5 : ";v
140 end
7000 ' descripteur de dialogue, lu sur place : Rect de la fenetre (ecran), options (bit 0 barre de titre), titre ;
7005 ' puis chaque element : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ, 6 texte fixe), options (bit 0 inactif,
7010 ' bit 1 par defaut : Entree, bit 2 annulation : Echap), Rect relatif au contenu, maximum, texte precede de sa
7015 ' longueur (un champ de texte reserve 1 + maximum octets) ; un 0 termine la liste. Adresse dans rg.
7020 rg = alloc(111) : p = rg
7025 for k = 1 to 4 : read v : doke p, v : p = p + 2 : next k : read v : poke p, v : p = p + 1 : read s$ : gosub 7100
7030 for it = 1 to 5 : read ty, op : poke p, ty : poke p + 1, op : p = p + 2
7035 for k = 1 to 5 : read v : doke p, v : p = p + 2 : next k : read s$ : p0 = p : gosub 7100
7040 if ty = 5 then p = p0 + 1 + v : ' le champ reserve 1 + maximum octets
7045 next it : poke p, 0 : ch = rg + 81 : return : ' ch : tampon de l'element 4
7050 data 40, 40, 240, 160, 1, "Reglages"
7055 data 1, 2, 130, 90, 190, 104, 0, "OK" : ' 1 : bouton par defaut
7060 data 1, 4, 60, 90, 120, 104, 0, "Annuler" : ' 2 : annulation
7065 data 2, 0, 10, 10, 100, 22, 0, "Son" : ' 3 : case a cocher
7070 data 5, 0, 10, 30, 150, 44, 8, "ab" : ' 4 : champ de texte, 8 au plus
7075 data 6, 0, 10, 50, 150, 60, 0, "Bonjour" : ' 5 : texte fixe
7100 poke p, len(s$) : for i = 1 to len(s$) : poke p + i, asc(mid$(s$, i, 1)) : next i : p = p + len(s$) + 1 : return
8000 ' 37,1 New Dialog sur le descripteur q : dialogue dans dg, fenetre dans fw, erreur dans e
8010 while peek($ff00) : wend : doke $ff04, q : f = 1 : gosub 8110
8020 dg = peek($ff06) : fw = peek($ff07) : return
8100 ' appel 37,f, parametres deja poses ; erreur dans e
8110 poke $ff01, f : poke $ff00, 37
8120 while peek($ff00) : wend : e = peek($ff02) : return
8200 ' 37,2 Dispose Dialog dg
8210 while peek($ff00) : wend : poke $ff04, dg : f = 2 : goto 8110
8300 ' 32,19 Toolbox Reset
8310 while peek($ff00) : wend : poke $ff01, 19 : poke $ff00, 32
8320 while peek($ff00) : wend : return
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Elements : 1/1 2/1 3/2 4/5 0/6
Case cochee par 36,5 : 1
Assembleur 65C02 (64tass)
; Lire le contrôle d'un élément (groupe 37, 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 #<b0
        ldx #>b0
        jsr envoi
        jsr ouvrir
        ldx #1
_el:    phx
        jsr WaitMessage
        plx
        stx ControlPort+5          ; P1 : élément
        phx
        lda dlg
        ldx #4                     ; Get Dialog Item
        jsr dial
        plx
        lda ControlPort+6          ; contrôle du groupe 36, 0 pour un texte fixe
        sta c-1,x
        lda ControlPort+7          ; type
        sta t-1,x
        inx
        cpx #6
        bne _el
        jsr WaitMessage
        lda c+2
        sta ControlPort+4
        lda #1
        sta ControlPort+5
        stz ControlPort+6
        lda #36
        ldx #5                     ; 36,5 : coche la case
        jsr appel
        jsr WaitMessage
        lda c+2
        sta ControlPort+4
        lda #36
        ldx #6
        jsr appel
        lda ControlPort+5
        sta v
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<t2
        ldx #>t2
        jsr ecrire
        ldx #0
_af:    lda #' '
        jsr WriteCharacter
        lda c,x
        jsr decimal
        lda #'/'
        jsr WriteCharacter
        lda t,x
        jsr decimal
        inx
        cpx #5
        bne _af
        lda #13
        jsr WriteCharacter
        lda #<t3
        ldx #>t3
        jsr ecrire
        lda v
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

; Descripteur de dialogue, lu sur place : Rect de la fenêtre (écran), options (bit 0 barre de titre), titre ;
; puis chaque élément : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ de texte, 6 texte fixe), options
; (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation : Échap), Rect relatif au contenu, maximum,
; texte précédé de sa longueur (un champ de texte réserve 1 + maximum octets) ; un 0 termine la liste.
reglages: .word 40, 40, 240, 160
        .byte 1, 8
        .text "Reglages"
type1:  .byte 1, 2                 ; 1 : bouton par défaut
        .word 130, 90, 190, 104, 0
        .byte 2
        .text "OK"
        .byte 1, 4                 ; 2 : annulation
        .word 60, 90, 120, 104, 0
        .byte 7
        .text "Annuler"
        .byte 2, 0                 ; 3 : case à cocher
        .word 10, 10, 100, 22, 0
        .byte 3
        .text "Son"
        .byte 5, 0                 ; 4 : champ de texte, 8 au plus
        .word 10, 30, 150, 44, 8
champ:  .byte 2
        .text "ab"
        .fill 6
        .byte 6, 0                 ; 5 : texte fixe
        .word 10, 50, 150, 60, 0
        .byte 7
        .text "Bonjour"
        .byte 0
c:      .fill 5
t:      .fill 5
b0:     .byte 32, 19, 0            ; 32,19 Toolbox Reset
v:      .byte 0
b1:     .byte 32, 19, 0            ; 32,19 Toolbox Reset
t2:     .text "Elements :", 0
t3:     .text "Case cochee par 36,5 : ", 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

; 37,1 New Dialog sur le descripteur reglages : dialogue dans dlg, fenêtre dans fen ; erreur dans A.
ouvrir: jsr WaitMessage
        lda #<reglages
        sta ControlPort+4
        lda #>reglages
        sta ControlPort+5
        lda #37
        ldx #1
        jsr appel
        lda ControlPort+6
        sta dlg
        lda ControlPort+7
        sta fen
        lda ControlPort+2
        rts

; 37,X sur le dialogue A.
dial:   pha
        phx
        jsr WaitMessage
        plx
        pla
        sta ControlPort+4
        lda #37
        jmp appel

dlg:    .byte 0
fen:    .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
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Elements : 1/1 2/1 3/2 4/5 0/6
Case cochee par 36,5 : 1

37,5 Draw Dialog Trinity

Redessine les contrôles et les textes fixes d'un dialogue.

Entrées
OctetsTypeRôle
P0uint8numéro du dialogue

Sorties : aucune.

Par exemple après que le programme a changé un texte dans le descripteur. L'exemple peint le contenu en couleur 4 : le cadre du bouton OK redevient blanc (15). NeoBASIC n'a pas de mot-clé pour cet appel.

Texte de la documentation du firmware (anglais)

Redraws the controls and static texts of dialog Parameter:0 (after the program changed a text in the descriptor, for instance).

C (llvm-mos)
/* Redessiner un dialogue (groupe 37, 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)
        ;
}

/* Descripteur de dialogue, lu sur place : Rect de la fenêtre (écran), options (bit 0 barre de titre), titre ;
   puis chaque élément : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ de texte, 6 texte fixe), options
   (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation : Échap), Rect relatif au contenu, maximum,
   texte précédé de sa longueur (un champ de texte réserve 1 + maximum octets) ; un 0 termine la liste. */
#define W(v) (v) & 0xFF, (v) >> 8
static uint8_t reglages[] = {
    W(40), W(40), W(240), W(160), 1, 8, 'R', 'e', 'g', 'l', 'a', 'g', 'e', 's',
    1, 2, W(130), W(90), W(190), W(104), W(0), 2, 'O', 'K',                          /* 1 : bouton par défaut */
    1, 4, W(60), W(90), W(120), W(104), W(0), 7, 'A', 'n', 'n', 'u', 'l', 'e', 'r',   /* 2 : annulation */
    2, 0, W(10), W(10), W(100), W(22), W(0), 3, 'S', 'o', 'n',                 /* 3 : case à cocher */
    5, 0, W(10), W(30), W(150), W(44), W(8), 2, 'a', 'b', 0, 0, 0, 0, 0, 0,      /* 4 : champ de texte, 8 au plus */
    6, 0, W(10), W(50), W(150), W(60), W(0), 7, 'B', 'o', 'n', 'j', 'o', 'u', 'r',   /* 5 : texte fixe */
    0 };
#define CHAMP 81                                /* position du tampon de l'élément 4 dans le descripteur */

static void p16(uint8_t i, uint16_t v) {        /* paramètre 16 bits en Pi, Pi+1 */
    ControlPort.params[i] = v & 0xFF;
    ControlPort.params[i + 1] = v >> 8;
}
static void reinit(void) {                      /* 32,19 Toolbox Reset */
    libre();
    api(32, 19);
}
static uint8_t dialogue, fenetre;
static uint8_t ouvrir(uint8_t *descripteur) {   /* 37,1 New Dialog : rend l'indicateur d'erreur */
    libre();
    p16(0, (uint16_t)descripteur);
    api(37, 1);
    dialogue = ControlPort.params[2];
    fenetre = ControlPort.params[3];
    return ControlPort.error;
}
static void fermer(uint8_t d) {                 /* 37,2 Dispose Dialog */
    libre();
    ControlPort.params[0] = d;
    api(37, 2);
}

typedef struct { int16_t g, h, d, b; } Rect;
static Rect ecran = {0, 0, 320, 240};

static uint8_t pixel(int16_t x, int16_t y) {    /* 5,33 : couleur du fond en (x, y) */
    libre(); p16(0, x); p16(2, y); api(5, 33);
    return ControlPort.params[0];
}

int main(void) {
    uint8_t avant, peint, apres;
    putchar(12);                                /* écran effacé : on relit des pixels */
    reinit();
    ouvrir(reglages);
    avant = pixel(171, 141);                    /* coin du bouton OK (contenu en (41, 51)) */
    libre(); ControlPort.params[0] = fenetre; api(34, 12);   /* le programme peint le contenu en couleur 4 */
    libre(); ControlPort.params[0] = 4; api(32, 4);
    libre(); p16(0, (uint16_t)&ecran); api(32, 8);
    peint = pixel(171, 141);
    libre(); ControlPort.params[0] = dialogue; api(37, 5);   /* Draw Dialog */
    apres = pixel(171, 141);
    reinit();
    printf("Bouton OK : %u, peint : %u, redessine : %u\n", avant, peint, apres);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Bouton OK : 15, peint : 4, redessine : 15
Mad Pascal
// Redessiner un dialogue (groupe 37, fonction 5, Trinity).
program dl5;
uses crt, neo6502;
// Descripteur de dialogue (variable : le firmware écrit dans le champ de texte), lu sur place : Rect de la
// fenêtre (écran), options (bit 0 barre de titre), titre ; puis chaque élément : type (1 bouton, 2 case, 3 radio,
// 4 barre, 5 champ de texte, 6 texte fixe), options (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation :
// Échap), Rect relatif au contenu, maximum, texte précédé de sa longueur (un champ de texte réserve 1 + maximum
// octets) ; un 0 termine la liste.
var reglages: array[0..110] of byte = (
    40, 0, 40, 0, 240, 0, 160, 0, 1, 8, ord('R'), ord('e'), ord('g'), ord('l'), ord('a'), ord('g'), ord('e'), ord('s'),
    1, 2, 130, 0, 90, 0, 190, 0, 104, 0, 0, 0, 2, ord('O'), ord('K'),   // 1 : bouton par défaut
    1, 4, 60, 0, 90, 0, 120, 0, 104, 0, 0, 0, 7, ord('A'), ord('n'), ord('n'), ord('u'), ord('l'), ord('e'), ord('r'),   // 2 : annulation
    2, 0, 10, 0, 10, 0, 100, 0, 22, 0, 0, 0, 3, ord('S'), ord('o'), ord('n'),   // 3 : case à cocher
    5, 0, 10, 0, 30, 0, 150, 0, 44, 0, 8, 0, 2, ord('a'), ord('b'), 0, 0, 0, 0, 0, 0,   // 4 : champ de texte, 8 au plus
    6, 0, 10, 0, 50, 0, 150, 0, 60, 0, 0, 0, 7, ord('B'), ord('o'), ord('n'), ord('j'), ord('o'), ord('u'), ord('r'),   // 5 : texte fixe
    0);
const CHAMP = 81;                               // position du tampon de l'élément 4 dans le descripteur

var dialogue, fenetre: byte;

procedure appel(g, f: byte);                    // appel g,f (paramètres déjà posés)
begin
  NeoSendMessage(g, f);
  NeoWaitMessage;
end;

procedure reinit;                               // 32,19 Toolbox Reset
begin
  NeoWaitMessage;
  appel(32, 19);
end;

function ouvrir(descripteur: pointer): byte;    // 37,1 New Dialog : rend l'indicateur d'erreur
begin
  NeoWaitMessage;
  wordParams[0] := word(descripteur);
  appel(37, 1);
  dialogue := NeoMessage.params[2];
  fenetre := NeoMessage.params[3];
  result := NeoMessage.error;
end;

procedure fermer(d: byte);                      // 37,2 Dispose Dialog
begin
  NeoWaitMessage;
  NeoMessage.params[0] := d;
  appel(37, 2);
end;

type Rect = record g, h, d, b: smallint; end;
var ecran: Rect;
    avant, peint, apres: byte;
begin
  write(chr(12));                               // écran effacé : on relit des pixels
  ecran.g := 0; ecran.h := 0; ecran.d := 320; ecran.b := 240;
  reinit;
  ouvrir(@reglages);
  avant := NeoGetPixel(171, 141);               // coin du bouton OK (contenu en (41, 51))
  NeoWaitMessage; NeoMessage.params[0] := fenetre; appel(34, 12);   // le programme peint le contenu en couleur 4
  NeoMessage.params[0] := 4; appel(32, 4);
  wordParams[0] := word(@ecran); appel(32, 8);
  peint := NeoGetPixel(171, 141);
  NeoWaitMessage; NeoMessage.params[0] := dialogue; appel(37, 5);   // Draw Dialog
  apres := NeoGetPixel(171, 141);
  reinit;
  writeln('Bouton OK : ', avant, ', peint : ', peint, ', redessine : ', apres);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Bouton OK : 15, peint : 4, redessine : 15
NeoBASIC
10 ' Redessiner un dialogue (groupe 37, fonction 5, Trinity)
15 gosub 7000
20 cls : ' ecran efface : on relit des pixels
30 ec = alloc(8) : doke ec, 0 : doke ec + 2, 0 : doke ec + 4, 320 : doke ec + 6, 240
40 gosub 8300
50 q = rg : gosub 8000
60 av = point(171, 141) : ' coin du bouton OK (contenu en (41, 51))
70 while peek($ff00) : wend : poke $ff04, fw : poke $ff01, 12 : poke $ff00, 34 : ' le programme peint le contenu en couleur 4
80 while peek($ff00) : wend : poke $ff04, 4 : poke $ff01, 4 : poke $ff00, 32
90 while peek($ff00) : wend : doke $ff04, ec : poke $ff01, 8 : poke $ff00, 32
100 while peek($ff00) : wend : pe = point(171, 141)
110 poke $ff04, dg : f = 5 : gosub 8110 : ' Draw Dialog
120 ap = point(171, 141)
130 gosub 8300
140 print "Bouton OK : ";av;", peint : ";pe;", redessine : ";ap
150 end
7000 ' descripteur de dialogue, lu sur place : Rect de la fenetre (ecran), options (bit 0 barre de titre), titre ;
7005 ' puis chaque element : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ, 6 texte fixe), options (bit 0 inactif,
7010 ' bit 1 par defaut : Entree, bit 2 annulation : Echap), Rect relatif au contenu, maximum, texte precede de sa
7015 ' longueur (un champ de texte reserve 1 + maximum octets) ; un 0 termine la liste. Adresse dans rg.
7020 rg = alloc(111) : p = rg
7025 for k = 1 to 4 : read v : doke p, v : p = p + 2 : next k : read v : poke p, v : p = p + 1 : read s$ : gosub 7100
7030 for it = 1 to 5 : read ty, op : poke p, ty : poke p + 1, op : p = p + 2
7035 for k = 1 to 5 : read v : doke p, v : p = p + 2 : next k : read s$ : p0 = p : gosub 7100
7040 if ty = 5 then p = p0 + 1 + v : ' le champ reserve 1 + maximum octets
7045 next it : poke p, 0 : ch = rg + 81 : return : ' ch : tampon de l'element 4
7050 data 40, 40, 240, 160, 1, "Reglages"
7055 data 1, 2, 130, 90, 190, 104, 0, "OK" : ' 1 : bouton par defaut
7060 data 1, 4, 60, 90, 120, 104, 0, "Annuler" : ' 2 : annulation
7065 data 2, 0, 10, 10, 100, 22, 0, "Son" : ' 3 : case a cocher
7070 data 5, 0, 10, 30, 150, 44, 8, "ab" : ' 4 : champ de texte, 8 au plus
7075 data 6, 0, 10, 50, 150, 60, 0, "Bonjour" : ' 5 : texte fixe
7100 poke p, len(s$) : for i = 1 to len(s$) : poke p + i, asc(mid$(s$, i, 1)) : next i : p = p + len(s$) + 1 : return
8000 ' 37,1 New Dialog sur le descripteur q : dialogue dans dg, fenetre dans fw, erreur dans e
8010 while peek($ff00) : wend : doke $ff04, q : f = 1 : gosub 8110
8020 dg = peek($ff06) : fw = peek($ff07) : return
8100 ' appel 37,f, parametres deja poses ; erreur dans e
8110 poke $ff01, f : poke $ff00, 37
8120 while peek($ff00) : wend : e = peek($ff02) : return
8200 ' 37,2 Dispose Dialog dg
8210 while peek($ff00) : wend : poke $ff04, dg : f = 2 : goto 8110
8300 ' 32,19 Toolbox Reset
8310 while peek($ff00) : wend : poke $ff01, 19 : poke $ff00, 32
8320 while peek($ff00) : wend : return
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Bouton OK : 15, peint : 4, redessine : 15
Assembleur 65C02 (64tass)
; Redessiner un dialogue (groupe 37, 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
        jsr ouvrir
        lda #171                   ; coin du bouton OK (contenu en (41, 51))
        ldy #141
        jsr pixel
        sta av
        jsr WaitMessage
        lda fen
        sta ControlPort+4
        lda #34
        ldx #12                    ; le programme peint le contenu en couleur 4
        jsr appel
        lda #<b1
        ldx #>b1
        jsr envoi
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #171
        ldy #141
        jsr pixel
        sta pe
        lda dlg
        ldx #5                     ; Draw Dialog
        jsr dial
        lda #171
        ldy #141
        jsr pixel
        sta ap
        lda #<b3
        ldx #>b3
        jsr envoi
        lda #<t4
        ldx #>t4
        jsr ecrire
        lda av
        jsr decimal
        lda #<t5
        ldx #>t5
        jsr ecrire
        lda pe
        jsr decimal
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda ap
        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

; Descripteur de dialogue, lu sur place : Rect de la fenêtre (écran), options (bit 0 barre de titre), titre ;
; puis chaque élément : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ de texte, 6 texte fixe), options
; (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation : Échap), Rect relatif au contenu, maximum,
; texte précédé de sa longueur (un champ de texte réserve 1 + maximum octets) ; un 0 termine la liste.
reglages: .word 40, 40, 240, 160
        .byte 1, 8
        .text "Reglages"
type1:  .byte 1, 2                 ; 1 : bouton par défaut
        .word 130, 90, 190, 104, 0
        .byte 2
        .text "OK"
        .byte 1, 4                 ; 2 : annulation
        .word 60, 90, 120, 104, 0
        .byte 7
        .text "Annuler"
        .byte 2, 0                 ; 3 : case à cocher
        .word 10, 10, 100, 22, 0
        .byte 3
        .text "Son"
        .byte 5, 0                 ; 4 : champ de texte, 8 au plus
        .word 10, 30, 150, 44, 8
champ:  .byte 2
        .text "ab"
        .fill 6
        .byte 6, 0                 ; 5 : texte fixe
        .word 10, 50, 150, 60, 0
        .byte 7
        .text "Bonjour"
        .byte 0
ecran:  .word 0, 0, 320, 240
b0:     .byte 32, 19, 0            ; 32,19 Toolbox Reset
av:     .byte 0
b1:     .byte 32, 4, 1, 4          ; 32,4
b2:     .byte 32, 8, 2             ; 32,8
        .word ecran
pe:     .byte 0
ap:     .byte 0
b3:     .byte 32, 19, 0            ; 32,19 Toolbox Reset
t4:     .text "Bouton OK : ", 0
t5:     .text ", peint : ", 0
t6:     .text ", redessine : ", 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

; 37,1 New Dialog sur le descripteur reglages : dialogue dans dlg, fenêtre dans fen ; erreur dans A.
ouvrir: jsr WaitMessage
        lda #<reglages
        sta ControlPort+4
        lda #>reglages
        sta ControlPort+5
        lda #37
        ldx #1
        jsr appel
        lda ControlPort+6
        sta dlg
        lda ControlPort+7
        sta fen
        lda ControlPort+2
        rts

; 37,X sur le dialogue A.
dial:   pha
        phx
        jsr WaitMessage
        plx
        pla
        sta ControlPort+4
        lda #37
        jmp appel

dlg:    .byte 0
fen:    .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
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Bouton OK : 15, peint : 4, redessine : 15

37,6 Alert Trinity

Ouvre une alerte centrée à l'écran, avec un message et un ou deux boutons.

Entrées
OctetsTypeRôle
P0-P1addradresse du message, précédé de sa longueur (13 : à la ligne)
P2uint8boutons : 0 OK, 1 OK et Annuler, 2 Oui et Non
Sorties
OctetsTypeRôle
P3uint8numéro du dialogue
P4uint8sa fenêtre

L'élément 1 est le premier bouton (OK ou Oui, par défaut, à droite), l'élément 2 le second (Annuler ou Non, annulation), l'élément 3 le message. Comme pour un dialogue : 37,3 jusqu'à l'élément 1 ou 2, puis 37,2. Le message doit rester intact tant que l'alerte est ouverte. NeoBASIC n'a pas de mot-clé pour cet appel.

Texte de la documentation du firmware (anglais)

Opens an alert centred on the screen with the length-prefixed message at Parameters:0,1 (one line per character 13, 6x8 font) and, by Parameter:2, the buttons 0 OK, 1 OK and Cancel, 2 Yes and No ; returns the dialog number in Parameter:3 and its window in Parameter:4. Item 1 is the first button (OK / Yes, default, at the right), item 2 the second (Cancel / No, cancel), item 3 the message : run Dialog Event until item 1 or 2, then Dispose Dialog. The message must stay intact while the alert is up.

C (llvm-mos)
/* Ouvrir une alerte (groupe 37, 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)
        ;
}

/* Descripteur de dialogue, lu sur place : Rect de la fenêtre (écran), options (bit 0 barre de titre), titre ;
   puis chaque élément : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ de texte, 6 texte fixe), options
   (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation : Échap), Rect relatif au contenu, maximum,
   texte précédé de sa longueur (un champ de texte réserve 1 + maximum octets) ; un 0 termine la liste. */
#define W(v) (v) & 0xFF, (v) >> 8
static uint8_t reglages[] = {
    W(40), W(40), W(240), W(160), 1, 8, 'R', 'e', 'g', 'l', 'a', 'g', 'e', 's',
    1, 2, W(130), W(90), W(190), W(104), W(0), 2, 'O', 'K',                          /* 1 : bouton par défaut */
    1, 4, W(60), W(90), W(120), W(104), W(0), 7, 'A', 'n', 'n', 'u', 'l', 'e', 'r',   /* 2 : annulation */
    2, 0, W(10), W(10), W(100), W(22), W(0), 3, 'S', 'o', 'n',                 /* 3 : case à cocher */
    5, 0, W(10), W(30), W(150), W(44), W(8), 2, 'a', 'b', 0, 0, 0, 0, 0, 0,      /* 4 : champ de texte, 8 au plus */
    6, 0, W(10), W(50), W(150), W(60), W(0), 7, 'B', 'o', 'n', 'j', 'o', 'u', 'r',   /* 5 : texte fixe */
    0 };
#define CHAMP 81                                /* position du tampon de l'élément 4 dans le descripteur */

static void p16(uint8_t i, uint16_t v) {        /* paramètre 16 bits en Pi, Pi+1 */
    ControlPort.params[i] = v & 0xFF;
    ControlPort.params[i + 1] = v >> 8;
}
static void reinit(void) {                      /* 32,19 Toolbox Reset */
    libre();
    api(32, 19);
}
static uint8_t dialogue, fenetre;
static uint8_t ouvrir(uint8_t *descripteur) {   /* 37,1 New Dialog : rend l'indicateur d'erreur */
    libre();
    p16(0, (uint16_t)descripteur);
    api(37, 1);
    dialogue = ControlPort.params[2];
    fenetre = ControlPort.params[3];
    return ControlPort.error;
}
static void fermer(uint8_t d) {                 /* 37,2 Dispose Dialog */
    libre();
    ControlPort.params[0] = d;
    api(37, 2);
}

/* Événements fabriqués comme ceux du groupe 33 : type, message, message2, modificateurs, X, Y. */
typedef struct { uint8_t what, message, message2, modifiers; int16_t x, y; } EventRecord;
static EventRecord ev;
static uint8_t a_lui;
static uint8_t evenement(uint8_t d, uint8_t what, uint8_t m, uint8_t m2, int16_t x, int16_t y) {   /* 37,3 Dialog Event */
    ev.what = what; ev.message = m; ev.message2 = m2; ev.modifiers = 0; ev.x = x; ev.y = y;
    libre();
    ControlPort.params[0] = d;
    p16(1, (uint16_t)&ev);
    api(37, 3);
    a_lui = ControlPort.params[4];              /* 1 si l'événement appartenait au dialogue */
    return ControlPort.params[3];               /* élément qui a agi, 0 si aucun */
}

static const char message[] = "\024Tout effacer ?\rSur ?";   /* 13 : à la ligne */

static uint8_t alerte(uint8_t boutons) {        /* Alert : 0 OK, 1 OK et Annuler, 2 Oui et Non */
    libre();
    p16(0, (uint16_t)message);
    ControlPort.params[2] = boutons;
    api(37, 6);
    return ControlPort.params[3];               /* numéro du dialogue */
}

int main(void) {
    uint8_t d, t[3], i, ent, ech;
    reinit();
    d = alerte(2);
    for (i = 0; i < 3; i++) {
        libre(); ControlPort.params[0] = d; ControlPort.params[1] = i + 1; api(37, 4);
        t[i] = ControlPort.params[3];           /* 1 Oui (par défaut), 2 Non (annulation), 3 le message */
    }
    ent = evenement(d, 1, 13, 0x28, 0, 0);
    ech = evenement(d, 1, 27, 0x29, 0, 0);
    fermer(d);
    reinit();
    printf("Alerte : dialogue %u, types %u %u %u\nEntree : %u, Echap : %u\n", d, t[0], t[1], t[2], ent, ech);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Alerte : dialogue 1, types 1 1 6
Entree : 1, Echap : 2
Mad Pascal
// Ouvrir une alerte (groupe 37, fonction 6, Trinity).
program dl6;
uses crt, neo6502;
// Descripteur de dialogue (variable : le firmware écrit dans le champ de texte), lu sur place : Rect de la
// fenêtre (écran), options (bit 0 barre de titre), titre ; puis chaque élément : type (1 bouton, 2 case, 3 radio,
// 4 barre, 5 champ de texte, 6 texte fixe), options (bit 0 inactif, bit 1 par défaut : Entrée, bit 2 annulation :
// Échap), Rect relatif au contenu, maximum, texte précédé de sa longueur (un champ de texte réserve 1 + maximum
// octets) ; un 0 termine la liste.
var reglages: array[0..110] of byte = (
    40, 0, 40, 0, 240, 0, 160, 0, 1, 8, ord('R'), ord('e'), ord('g'), ord('l'), ord('a'), ord('g'), ord('e'), ord('s'),
    1, 2, 130, 0, 90, 0, 190, 0, 104, 0, 0, 0, 2, ord('O'), ord('K'),   // 1 : bouton par défaut
    1, 4, 60, 0, 90, 0, 120, 0, 104, 0, 0, 0, 7, ord('A'), ord('n'), ord('n'), ord('u'), ord('l'), ord('e'), ord('r'),   // 2 : annulation
    2, 0, 10, 0, 10, 0, 100, 0, 22, 0, 0, 0, 3, ord('S'), ord('o'), ord('n'),   // 3 : case à cocher
    5, 0, 10, 0, 30, 0, 150, 0, 44, 0, 8, 0, 2, ord('a'), ord('b'), 0, 0, 0, 0, 0, 0,   // 4 : champ de texte, 8 au plus
    6, 0, 10, 0, 50, 0, 150, 0, 60, 0, 0, 0, 7, ord('B'), ord('o'), ord('n'), ord('j'), ord('o'), ord('u'), ord('r'),   // 5 : texte fixe
    0);
const CHAMP = 81;                               // position du tampon de l'élément 4 dans le descripteur

var dialogue, fenetre: byte;

procedure appel(g, f: byte);                    // appel g,f (paramètres déjà posés)
begin
  NeoSendMessage(g, f);
  NeoWaitMessage;
end;

procedure reinit;                               // 32,19 Toolbox Reset
begin
  NeoWaitMessage;
  appel(32, 19);
end;

function ouvrir(descripteur: pointer): byte;    // 37,1 New Dialog : rend l'indicateur d'erreur
begin
  NeoWaitMessage;
  wordParams[0] := word(descripteur);
  appel(37, 1);
  dialogue := NeoMessage.params[2];
  fenetre := NeoMessage.params[3];
  result := NeoMessage.error;
end;

procedure fermer(d: byte);                      // 37,2 Dispose Dialog
begin
  NeoWaitMessage;
  NeoMessage.params[0] := d;
  appel(37, 2);
end;

// Événements fabriqués comme ceux du groupe 33 : type, message, message2, modificateurs, X, Y.
type EventRecord = record what, message, message2, modifiers: byte; x, y: smallint; end;
var ev: EventRecord;
    a_lui: byte;

function evenement(d, what, m, m2: byte; x, y: smallint): byte;   // 37,3 Dialog Event
begin
  ev.what := what; ev.message := m; ev.message2 := m2; ev.modifiers := 0; ev.x := x; ev.y := y;
  NeoWaitMessage;
  NeoMessage.params[0] := d;
  NeoMessage.params[1] := lo(word(@ev));
  NeoMessage.params[2] := hi(word(@ev));
  appel(37, 3);
  a_lui := NeoMessage.params[4];                // 1 si l'événement appartenait au dialogue
  result := NeoMessage.params[3];               // élément qui a agi, 0 si aucun
end;

const message: array[0..20] of byte = (20, ord('T'), ord('o'), ord('u'), ord('t'), ord(' '), ord('e'), ord('f'), ord('f'),
        ord('a'), ord('c'), ord('e'), ord('r'), ord(' '), ord('?'), 13, ord('S'), ord('u'), ord('r'), ord(' '), ord('?'));   // 13 : à la ligne

function alerte(boutons: byte): byte;           // Alert : 0 OK, 1 OK et Annuler, 2 Oui et Non
begin
  NeoWaitMessage;
  wordParams[0] := word(@message);
  NeoMessage.params[2] := boutons;
  appel(37, 6);
  result := NeoMessage.params[3];               // numéro du dialogue
end;

var d, i, ent, ech: byte;
    t: array[0..2] of byte;
begin
  reinit;
  d := alerte(2);
  for i := 0 to 2 do begin
    NeoWaitMessage; NeoMessage.params[0] := d; NeoMessage.params[1] := i + 1; appel(37, 4);
    t[i] := NeoMessage.params[3];               // 1 Oui (par défaut), 2 Non (annulation), 3 le message
  end;
  ent := evenement(d, 1, 13, $28, 0, 0);
  ech := evenement(d, 1, 27, $29, 0, 0);
  fermer(d);
  reinit;
  writeln('Alerte : dialogue ', d, ', types ', t[0], ' ', t[1], ' ', t[2]);
  writeln('Entree : ', ent, ', Echap : ', ech);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Alerte : dialogue 1, types 1 1 6
Entree : 1, Echap : 2
NeoBASIC
10 ' Ouvrir une alerte (groupe 37, fonction 6, Trinity)
15 gosub 7000
20 ev = alloc(8)
30 m$ = "Tout effacer ?" + chr$(13) + "Sur ?" : ' 13 : a la ligne
40 mg = alloc(len(m$) + 1) : poke mg, len(m$) : for i = 1 to len(m$) : poke mg + i, asc(mid$(m$, i, 1)) : next i
50 gosub 8300
60 while peek($ff00) : wend : doke $ff04, mg : poke $ff06, 2 : f = 6 : gosub 8110 : ' Alert : 2 = Oui et Non
70 dg = peek($ff07)
80 dim t(2) : for k = 0 to 2
90 while peek($ff00) : wend : poke $ff04, dg : poke $ff05, k + 1 : f = 4 : gosub 8110 : t(k) = peek($ff07) : next k
100 wh = 1 : ms = 13 : m2 = $28 : ex = 0 : ey = 0 : gosub 7500 : en = it
110 ms = 27 : m2 = $29 : gosub 7500 : ec = it
120 gosub 8200 : gosub 8300
130 print "Alerte : dialogue ";dg;", types ";t(0);" ";t(1);" ";t(2)
140 print "Entree : ";en;", Echap : ";ec
150 end
7500 ' 37,3 Dialog Event : evenement fabrique (type wh, message ms, message2 m2, X ex, Y ey) pour le dialogue dg
7510 ' element qui a agi dans it (0 si aucun), al = 1 si l'evenement appartenait au dialogue
7520 poke ev, wh : poke ev + 1, ms : poke ev + 2, m2 : poke ev + 3, 0 : doke ev + 4, ex : doke ev + 6, ey
7530 while peek($ff00) : wend : poke $ff04, dg : doke $ff05, ev : f = 3 : gosub 8110
7540 it = peek($ff07) : al = peek($ff08) : return
7000 ' descripteur de dialogue, lu sur place : Rect de la fenetre (ecran), options (bit 0 barre de titre), titre ;
7005 ' puis chaque element : type (1 bouton, 2 case, 3 radio, 4 barre, 5 champ, 6 texte fixe), options (bit 0 inactif,
7010 ' bit 1 par defaut : Entree, bit 2 annulation : Echap), Rect relatif au contenu, maximum, texte precede de sa
7015 ' longueur (un champ de texte reserve 1 + maximum octets) ; un 0 termine la liste. Adresse dans rg.
7020 rg = alloc(111) : p = rg
7025 for k = 1 to 4 : read v : doke p, v : p = p + 2 : next k : read v : poke p, v : p = p + 1 : read s$ : gosub 7100
7030 for it = 1 to 5 : read ty, op : poke p, ty : poke p + 1, op : p = p + 2
7035 for k = 1 to 5 : read v : doke p, v : p = p + 2 : next k : read s$ : p0 = p : gosub 7100
7040 if ty = 5 then p = p0 + 1 + v : ' le champ reserve 1 + maximum octets
7045 next it : poke p, 0 : ch = rg + 81 : return : ' ch : tampon de l'element 4
7050 data 40, 40, 240, 160, 1, "Reglages"
7055 data 1, 2, 130, 90, 190, 104, 0, "OK" : ' 1 : bouton par defaut
7060 data 1, 4, 60, 90, 120, 104, 0, "Annuler" : ' 2 : annulation
7065 data 2, 0, 10, 10, 100, 22, 0, "Son" : ' 3 : case a cocher
7070 data 5, 0, 10, 30, 150, 44, 8, "ab" : ' 4 : champ de texte, 8 au plus
7075 data 6, 0, 10, 50, 150, 60, 0, "Bonjour" : ' 5 : texte fixe
7100 poke p, len(s$) : for i = 1 to len(s$) : poke p + i, asc(mid$(s$, i, 1)) : next i : p = p + len(s$) + 1 : return
8000 ' 37,1 New Dialog sur le descripteur q : dialogue dans dg, fenetre dans fw, erreur dans e
8010 while peek($ff00) : wend : doke $ff04, q : f = 1 : gosub 8110
8020 dg = peek($ff06) : fw = peek($ff07) : return
8100 ' appel 37,f, parametres deja poses ; erreur dans e
8110 poke $ff01, f : poke $ff00, 37
8120 while peek($ff00) : wend : e = peek($ff02) : return
8200 ' 37,2 Dispose Dialog dg
8210 while peek($ff00) : wend : poke $ff04, dg : f = 2 : goto 8110
8300 ' 32,19 Toolbox Reset
8310 while peek($ff00) : wend : poke $ff01, 19 : poke $ff00, 32
8320 while peek($ff00) : wend : return
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Alerte : dialogue 1, types 1 1 6
Entree : 1, Echap : 2
Assembleur 65C02 (64tass)
; Ouvrir une alerte (groupe 37, 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 #<b0
        ldx #>b0
        jsr envoi
        lda #<b1
        ldx #>b1
        jsr envoi
        lda ControlPort+7          ; numéro du dialogue
        sta d
        ldx #1
_el:    phx
        jsr WaitMessage
        plx
        stx ControlPort+5
        phx
        lda d
        ldx #4                     ; 37,4 : 1 Oui (par défaut), 2 Non (annulation), 3 le message
        jsr dial
        plx
        lda ControlPort+7
        sta t-1,x
        inx
        cpx #4
        bne _el
        lda #1
        sta ev
        lda #13
        sta ev+1
        lda #$28
        sta ev+2
        lda #0
        sta ev+4
        lda #0                  
        sta ev+6
        lda d
        jsr evenement
        sta en
        lda #1
        sta ev
        lda #27
        sta ev+1
        lda #$29
        sta ev+2
        lda #0
        sta ev+4
        lda #0                  
        sta ev+6
        lda d
        jsr evenement
        sta ec
        lda d
        ldx #2                     ; 37,2
        jsr dial
        lda #<b2
        ldx #>b2
        jsr envoi
        lda #<t3
        ldx #>t3
        jsr ecrire
        lda d
        jsr decimal
        lda #<t4
        ldx #>t4
        jsr ecrire
        lda t
        jsr decimal
        lda #<t5
        ldx #>t5
        jsr ecrire
        lda t+1
        jsr decimal
        lda #<t6
        ldx #>t6
        jsr ecrire
        lda t+2
        jsr decimal
        lda #13
        jsr WriteCharacter
        lda #<t7
        ldx #>t7
        jsr ecrire
        lda en
        jsr decimal
        lda #<t8
        ldx #>t8
        jsr ecrire
        lda ec
        jsr decimal
        lda #13
        jsr WriteCharacter
        rts

message: .byte 20
        .text "Tout effacer ?", 13, "Sur ?"   ; 13 : à la ligne
t:      .fill 3
b0:     .byte 32, 19, 0            ; 32,19 Toolbox Reset
b1:     .byte 37, 6, 3             ; Alert : 2 = Oui et Non
        .word message
        .byte 2
d:      .byte 0
en:     .byte 0
ec:     .byte 0
b2:     .byte 32, 19, 0            ; 32,19 Toolbox Reset
t3:     .text "Alerte : dialogue ", 0
t4:     .text ", types ", 0
t5:     .text " ", 0
t6:     .text " ", 0
t7:     .text "Entree : ", 0
t8:     .text ", Echap : ", 0

; 37,3 Dialog Event : l'événement ev (fabriqué comme ceux du groupe 33 : type, message, message2,
; modificateurs, X, Y) pour le dialogue A ; élément qui a agi dans A (0 si aucun), appartenance dans alui.
evenement:
        pha
        jsr WaitMessage
        pla
        sta ControlPort+4
        lda #<ev
        sta ControlPort+5
        lda #>ev
        sta ControlPort+6
        lda #37
        ldx #3
        jsr appel
        lda ControlPort+8          ; 1 si l'événement appartenait au dialogue
        sta alui
        lda ControlPort+7          ; élément qui a agi
        rts
ev:     .byte 0, 0, 0, 0
        .word 0, 0
alui:   .byte 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

; 37,X sur le dialogue A.
dial:   pha
        phx
        jsr WaitMessage
        plx
        pla
        sta ControlPort+4
        lda #37
        jmp appel

dlg:    .byte 0
fen:    .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
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Alerte : dialogue 1, types 1 1 6
Entree : 1, Echap : 2

← L'API du Neo6502