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.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of the descriptor (read in place) |
| Bytes | Type | Meaning |
|---|---|---|
P2 | uint8 | dialog number (1 or 2) |
P3 | uint8 | its window (group 34) |
erreur | uint8 | 1 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;
}Dialogue 1, fenetre 1 ; type 9 : erreur 1Mad 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.Dialogue 1, fenetre 1 ; type 9 : erreur 1NeoBASIC
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 : returnDialogue 1, fenetre 1 ; type 9 : erreur 165C02 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 0Dialogue 1, fenetre 1 ; type 9 : erreur 137,2 Dispose Dialog Trinity
Closes a dialog: its window and controls are disposed.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | dialog 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;
}Fenetre devant : 1, puis 0 ; nouveau dialogue : 1Mad 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.Fenetre devant : 1, puis 0 ; nouveau dialogue : 1NeoBASIC
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 : returnFenetre devant : 1, puis 0 ; nouveau dialogue : 165C02 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 0Fenetre devant : 1, puis 0 ; nouveau dialogue : 137,3 Dialog Event Trinity
Gives an event (group 33) to the dialog and returns the item that acted.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | dialog number |
P1-P2 | addr | address of the EventRecord |
| Bytes | Type | Meaning |
|---|---|---|
P3 | uint8 | item that acted (1, 2... in descriptor order), 0 if none |
P4 | uint8 | 1 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;
}X : element 4, champ : abX
Son : 3, Entree : 1, Echap : 2
Minuteur : 0, au dialogue : 0Mad 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.X : element 4, champ : abX
Son : 3, Entree : 1, Echap : 2
Minuteur : 0, au dialogue : 0NeoBASIC
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 : returnX : element 4, champ : abX
Son : 3, Entree : 1, Echap : 2
Minuteur : 0, au dialogue : 065C02 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 0X : element 4, champ : abX
Son : 3, Entree : 1, Echap : 2
Minuteur : 0, au dialogue : 037,4 Get Dialog Item Trinity
Returns the control (group 36) and the kind of a dialog item.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | dialog number |
P1 | uint8 | item number (1, 2...) |
| Bytes | Type | Meaning |
|---|---|---|
P2 | uint8 | group 36 control (0 for static text) |
P3 | uint8 | item 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;
}Elements : 1/1 2/1 3/2 4/5 0/6
Case cochee par 36,5 : 1Mad 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.Elements : 1/1 2/1 3/2 4/5 0/6
Case cochee par 36,5 : 1NeoBASIC
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 : returnElements : 1/1 2/1 3/2 4/5 0/6
Case cochee par 36,5 : 165C02 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 0Elements : 1/1 2/1 3/2 4/5 0/6
Case cochee par 36,5 : 137,5 Draw Dialog Trinity
Redraws the controls and static texts of a dialog.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | dialog 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;
}Bouton OK : 15, peint : 4, redessine : 15Mad 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.Bouton OK : 15, peint : 4, redessine : 15NeoBASIC
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 : returnBouton OK : 15, peint : 4, redessine : 1565C02 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 0Bouton OK : 15, peint : 4, redessine : 1537,6 Alert Trinity
Opens an alert centred on the screen, with a message and one or two buttons.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of the message, preceded by its length (13: new line) |
P2 | uint8 | buttons: 0 OK, 1 OK and Cancel, 2 Yes and No |
| Bytes | Type | Meaning |
|---|---|---|
P3 | uint8 | dialog number |
P4 | uint8 | its 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;
}Alerte : dialogue 1, types 1 1 6
Entree : 1, Echap : 2Mad 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.Alerte : dialogue 1, types 1 1 6
Entree : 1, Echap : 2NeoBASIC
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 : returnAlerte : dialogue 1, types 1 1 6
Entree : 1, Echap : 265C02 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 0Alerte : dialogue 1, types 1 1 6
Entree : 1, Echap : 2