Tachibana
Language: English

Group 37 — Dialog Manager 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

The dialog manager of the Trinity toolbox builds modal dialogs (2 at most) and alerts, with windows (group 34) and controls (group 36).

Dialog descriptor, in 6502 RAM: the window Rect (screen coordinates), 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 button, 4 scroll bar, 5 text field, 6 static text), flags (bit 0 disabled, bit 1 default, fired by Return, bit 2 cancel, fired by Escape), Rect relative to the content, 16-bit maximum (scroll bar value or text field length), length-prefixed text (a text field reserves 1 + maximum bytes; static text breaks the line at each character 13).

The dialog of the examples: "Reglages", with OK (default), Annuler (cancel), a "Son" check box, an "ab" text field of 8 characters at most and a static text. The examples build the events they give it and reset the toolbox with 32,19 at the start and at the end.

37,1 New Dialog Trinity

Builds a modal dialog from a descriptor in 6502 RAM and draws it.

Inputs
BytesTypeMeaning
P0-P1addraddress of the descriptor (read in place)
Outputs
BytesTypeMeaning
P2uint8dialog number (1 or 2)
P3uint8its window (group 34)
erreuruint81 bad descriptor, 2 no dialog, window or control left

The descriptor (see the introduction) must stay intact while the dialog is open: the firmware reads it again and writes into the buffer of text fields. Items 1 to 5 are controls of group 36 (see 37,4). Keys go to the first enabled text field (Tab: to the next one). An unknown item kind is refused. NeoBASIC has no keyword for this call.

Firmware documentation text

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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 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.
Output observed in the Phosphoneo emulator, Trinity firmware 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
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Dialogue 1, fenetre 1 ; type 9 : erreur 1
65C02 assembly (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
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Dialogue 1, fenetre 1 ; type 9 : erreur 1

37,2 Dispose Dialog Trinity

Closes a dialog: its window and controls are disposed.

Inputs
BytesTypeMeaning
P0uint8dialog number

Outputs: none.

The windows it covered get an update event. The dialog number is taken by the next one. NeoBASIC has no keyword for this call.

Firmware documentation text

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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 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.
Output observed in the Phosphoneo emulator, Trinity firmware 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
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Fenetre devant : 1, puis 0 ; nouveau dialogue : 1
65C02 assembly (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
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Fenetre devant : 1, puis 0 ; nouveau dialogue : 1

37,3 Dialog Event Trinity

Gives an event (group 33) to the dialog and returns the item that acted.

Inputs
BytesTypeMeaning
P0uint8dialog number
P1-P2addraddress of the EventRecord
Outputs
BytesTypeMeaning
P3uint8item that acted (1, 2... in descriptor order), 0 if none
P4uint81 if the event belonged to the dialog

An item acts when: a button is released inside it, Return (default item), Escape (cancel item), a box toggles, a scroll bar moves, a text field is clicked or edited. While the dialog is up, all mouse and key events belong to it, even a click outside its window (measured on the bench); updates of other windows and timers stay with the program. The example builds its events; a program passes those of 33,2 until it gets the item it waits for, then calls 37,2. NeoBASIC has no keyword for this call.

Firmware documentation text

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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 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.
Output observed in the Phosphoneo emulator, Trinity firmware 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
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
X : element 4, champ : abX
Son : 3, Entree : 1, Echap : 2
Minuteur : 0, au dialogue : 0
65C02 assembly (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
Output observed in the Phosphoneo emulator, Trinity firmware 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

Returns the control (group 36) and the kind of a dialog item.

Inputs
BytesTypeMeaning
P0uint8dialog number
P1uint8item number (1, 2...)
Outputs
BytesTypeMeaning
P2uint8group 36 control (0 for static text)
P3uint8item kind

The control is then driven with group 36: the example checks the box with 36,5 and reads it back with 36,6. NeoBASIC has no keyword for this call.

Firmware documentation text

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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 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.
Output observed in the Phosphoneo emulator, Trinity firmware 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
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Elements : 1/1 2/1 3/2 4/5 0/6
Case cochee par 36,5 : 1
65C02 assembly (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
Output observed in the Phosphoneo emulator, Trinity firmware 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

Redraws the controls and static texts of a dialog.

Inputs
BytesTypeMeaning
P0uint8dialog number

Outputs: none.

For instance after the program changed a text in the descriptor. The example paints the content in colour 4: the frame of the OK button turns white (15) again. NeoBASIC has no keyword for this call.

Firmware documentation text

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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 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.
Output observed in the Phosphoneo emulator, Trinity firmware 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
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Bouton OK : 15, peint : 4, redessine : 15
65C02 assembly (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
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Bouton OK : 15, peint : 4, redessine : 15

37,6 Alert Trinity

Opens an alert centred on the screen, with a message and one or two buttons.

Inputs
BytesTypeMeaning
P0-P1addraddress of the message, preceded by its length (13: new line)
P2uint8buttons: 0 OK, 1 OK and Cancel, 2 Yes and No
Outputs
BytesTypeMeaning
P3uint8dialog number
P4uint8its window

Item 1 is the first button (OK or Yes, default, at the right), item 2 the second (Cancel or No, cancel), item 3 the message. As for a dialog: 37,3 until item 1 or 2, then 37,2. The message must stay intact while the alert is up. NeoBASIC has no keyword for this call.

Firmware documentation text

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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 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.
Output observed in the Phosphoneo emulator, Trinity firmware 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
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Alerte : dialogue 1, types 1 1 6
Entree : 1, Echap : 2
65C02 assembly (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
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Alerte : dialogue 1, types 1 1 6
Entree : 1, Echap : 2

← The Neo6502 API