Groupe 2 — Console Officiel
2,0 Write Character · 2,1 Read Character · 2,2 Console Status · 2,3 Read Line · 2,4 Define Hotkey · 2,5 Define Character · 2,6 Write Character · 2,7 Set Cursor Pos · 2,8 List Hotkeys · 2,9 Screen Size · 2,10 Insert Line · 2,11 Delete Line · 2,12 Clear Screen · 2,13 Cursor Position · 2,14 Clear Region · 2,15 Set Text Color · 2,16 Cursor Inverse · 2,17 Tab() implementation · 2,18 Read Ink/Paper Colours · 2,19 Show/Hide Cursor Reversing · 2,20 Console Debug Echo · 2,21 Set Console Font · 2,22 Get Media Key · 2,23 Get Lock Keys
2,0 Write Character Officiel
Écrit un caractère à la position du curseur. Doublon de la fonction 2,6, conservé pour la compatibilité.
| Octets | Type | Rôle |
|---|---|---|
P0 | char | le caractère (ou un code de contrôle, voir 2,6) |
Sorties : aucune.
Préférer la fonction 2,6, qui fait la même chose.
Texte de la documentation du firmware (anglais)
Console out (duplicate of Function 6 for backward compatibility).
C (llvm-mos)
/* Écrire un texte caractère par caractère (groupe 2, fonction 0). */
#include <neo6502.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)
;
}
int main(void) {
const char *texte = "Bonjour\r";
while (*texte) {
libre();
ControlPort.params[0] = *texte++;
api(2, 0); /* Write Character */
}
return 0;
}BonjourMad Pascal
// Écrire un texte caractère par caractère (groupe 2, fonction 0).
program ecrire0;
uses crt, neo6502;
var texte: string[16];
i: byte;
begin
texte := 'Bonjour';
for i := 1 to length(texte) do
begin
NeoWaitMessage;
NeoMessage.params[0] := ord(texte[i]);
NeoSendMessage(2, 0); // Write Character
end;
NeoWaitMessage;
NeoMessage.params[0] := 13; // retour à la ligne
NeoSendMessage(2, 0);
NeoWaitMessage;
end.BonjourNeoBASIC
10 ' Ecrire un texte caractere par caractere (groupe 2, fonction 0)
20 t$ = "Bonjour" + chr$(13)
30 for i = 1 to len(t$)
40 while peek($ff00) : wend
50 poke $ff04, asc(mid$(t$, i, 1)) : poke $ff01, 0 : poke $ff00, 2
60 next i
70 while peek($ff00) : wendBonjourAssembleur 65C02 (64tass)
; Écrire un texte caractère par caractère (groupe 2, fonction 0).
.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: ldx #0
_suiv: lda texte,x
beq _fin
jsr WaitMessage
sta ControlPort+4 ; P0 : le caractère
phx
lda #2
ldx #0 ; fonction 0 : Write Character
jsr appel
plx
inx
bne _suiv
_fin: rts
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
texte: .text "Bonjour", 13, 0Bonjour2,1 Read Character Officiel
Retire la touche la plus ancienne de la file du clavier et donne son code ASCII ; 0 si la file est vide.
Entrées : aucune.
| Octets | Type | Rôle |
|---|---|---|
P0 | char | code ASCII de la touche, 0 si aucune |
Faite pour la saisie de texte. Pour un jeu, lire l'état des touches (1,2 ou 7,1) : la file ne dit pas si une touche est encore enfoncée. En NeoBASIC, inkey$() fait le même appel.
Mots-clés NeoBASIC qui font cet appel : inkey$()
Texte de la documentation du firmware (anglais)
Read and remove a key press from the keyboard queue into Parameter:0. This is the ASCII value of the keystroke. If there are no key presses in the queue, Parameter:0 will be zero.
Note that this Function is best for text input, but not for games. Function 7,1 is more optimal for games, as this only detects key presses, you cannot check whether the key is currently down or not.
C (llvm-mos)
/* Attendre une touche et l'afficher (groupe 2, fonction 1). */
#include <stdio.h>
#include <neo/api.h>
int main(void) {
char c;
printf("Appuyez sur une touche\n");
while ((c = neo_console_read_char()) == 0) /* 0 : file vide */
;
printf("Touche : %c\n", c);
return 0;
}Appuyez sur une touche
Touche : AMad Pascal
// Attendre une touche et l'afficher (groupe 2, fonction 1).
program lecture;
uses crt, neo6502;
var c: byte;
begin
writeln('Appuyez sur une touche');
repeat
NeoSendMessage(2, 1); // Read Character
NeoWaitMessage;
c := NeoMessage.params[0];
until c <> 0; // 0 : file vide
writeln('Touche : ', chr(c));
end.Appuyez sur une touche
Touche : ANeoBASIC
10 ' Attendre une touche et l'afficher (groupe 2, fonction 1)
20 print "Appuyez sur une touche"
30 repeat : k$ = inkey$() : until k$ <> ""
40 print "Touche : ";k$Appuyez sur une touche
Touche : AAssembleur 65C02 (64tass)
; Attendre une touche et l'afficher (groupe 2, fonction 1).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<invite
ldx #>invite
jsr ecrire
_att: jsr WaitMessage
lda #2
ldx #1 ; fonction 1 : Read Character
jsr appel
lda ControlPort+4 ; P0 : la touche, 0 si aucune
beq _att
pha
lda #<message
ldx #>message
jsr ecrire
pla
jsr WriteCharacter
lda #13
jmp WriteCharacter
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
invite: .text "Appuyez sur une touche", 13, 0
message: .text "Touche : ", 0Appuyez sur une touche
Touche : A2,2 Console Status Officiel
Indique si la file du clavier est vide, sans rien en retirer.
Entrées : aucune.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | $FF si la file est vide, 0 si une touche attend |
Attention au sens : $FF signifie « rien à lire ».
Texte de la documentation du firmware (anglais)
Check to see if the keyboard queue is empty. If it is, Parameter:0 will be $FF, otherwise it will be $00
C (llvm-mos)
/* Attendre qu'une touche soit dans la file, sans la retirer (groupe 2, fonction 2). */
#include <stdio.h>
#include <neo/api.h>
int main(void) {
printf("Appuyez sur une touche\n");
while (neo_console_status() == 0xFF) /* $FF : file vide */
;
printf("Une touche attend\n");
neo_console_read_char(); /* la retirer de la file */
return 0;
}Appuyez sur une touche
Une touche attendMad Pascal
// Attendre qu'une touche soit dans la file, sans la retirer (groupe 2, fonction 2).
program statut;
uses crt, neo6502;
begin
writeln('Appuyez sur une touche');
repeat
NeoSendMessage(2, 2); // Console Status
NeoWaitMessage;
until NeoMessage.params[0] <> $FF; // $FF : file vide
writeln('Une touche attend');
NeoSendMessage(2, 1); // la retirer de la file
NeoWaitMessage;
end.Appuyez sur une touche
Une touche attendNeoBASIC
10 ' Attendre qu'une touche soit dans la file, sans la retirer (groupe 2, fonction 2)
20 print "Appuyez sur une touche"
30 repeat
40 while peek($ff00) : wend
50 poke $ff01, 2 : poke $ff00, 2
60 while peek($ff00) : wend : v = peek($ff04)
70 until v <> 255
80 print "Une touche attend"
90 k$ = inkey$()Appuyez sur une touche
Une touche attend
AAssembleur 65C02 (64tass)
; Attendre qu'une touche soit dans la file, sans la retirer (groupe 2, fonction 2).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<invite
ldx #>invite
jsr ecrire
_att: jsr WaitMessage
lda #2
ldx #2 ; fonction 2 : Console Status
jsr appel
lda ControlPort+4 ; $FF : file vide
cmp #$FF
beq _att
lda #<message
ldx #>message
jsr ecrire
jsr WaitMessage
lda #2
ldx #1 ; retirer la touche (2,1)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
invite: .text "Appuyez sur une touche", 13, 0
message: .text "Une touche attend", 13, 0Appuyez sur une touche
Une touche attend2,3 Read Line Officiel
Relit le texte de la ligne de l'écran où se trouve le curseur (une ligne logique, éventuellement sur plusieurs lignes d'écran), puis place le curseur au début de la ligne suivante.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse d'un tampon de 256 octets qui reçoit la ligne (longueur, puis texte) |
| Octets | Type | Rôle |
|---|---|---|
tampon | string | la ligne, sans les espaces de fin |
Rien n'est attendu au clavier : la fonction lit ce qui est déjà affiché. C'est ainsi qu'un éditeur plein écran récupère la ligne sur laquelle on a appuyé sur Entrée. Pour une vraie saisie, le noyau offre ReadLine ($FFEB).
Texte de la documentation du firmware (anglais)
Input the current line below the cursor into Parameters:0,1 as a length-prefixed string; and move the cursor to the line below. Handles multiple-line input.
C (llvm-mos)
/* Relire une ligne déjà affichée à l'écran (groupe 2, fonction 3). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t tampon[256]; /* longueur, puis le texte */
int main(void) {
printf("Bonjour tout le monde\n");
libre();
api(2, 13); /* Cursor Position */
uint8_t y = ControlPort.params[1];
libre();
ControlPort.params[0] = 0; /* remonter sur la ligne affichée */
ControlPort.params[1] = y - 1;
api(2, 7); /* Set Cursor Pos */
libre();
ControlPort.params[0] = (uint16_t)tampon & 0xFF;
ControlPort.params[1] = (uint16_t)tampon >> 8;
api(2, 3); /* Read Line */
printf("Relu : %.*s\n", tampon[0], tampon + 1);
return 0;
}Bonjour tout le monde
Relu : Bonjour tout le mondeMad Pascal
// Relire une ligne déjà affichée à l'écran (groupe 2, fonction 3).
program relire;
uses crt, neo6502;
var tampon: string[255]; // longueur, puis le texte
x, y: byte;
begin
writeln('Bonjour tout le monde');
NeoGetCursorPos(x, y);
NeoWaitMessage;
NeoMessage.params[0] := 0; // remonter sur la ligne affichée
NeoMessage.params[1] := y - 1;
NeoSendMessage(2, 7); // Set Cursor Pos
NeoWaitMessage;
wordParams[0] := word(@tampon);
NeoSendMessage(2, 3); // Read Line
NeoWaitMessage;
writeln('Relu : ', tampon);
end.Bonjour tout le monde
Relu : Bonjour tout le mondeNeoBASIC
10 ' Relire une ligne deja affichee a l'ecran (groupe 2, fonction 3)
20 a = alloc(256)
30 print "Bonjour tout le monde"
40 while peek($ff00) : wend
50 poke $ff01, 13 : poke $ff00, 2
60 while peek($ff00) : wend : y = peek($ff05)
70 poke $ff04, 0 : poke $ff05, y - 1 : poke $ff01, 7 : poke $ff00, 2
80 while peek($ff00) : wend
90 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 3 : poke $ff00, 2
100 while peek($ff00) : wend
110 r$ = "" : for i = 1 to peek(a) : r$ = r$ + chr$(peek(a + i)) : next i
120 print "Relu : ";r$Bonjour tout le monde
Relu : Bonjour tout le mondeAssembleur 65C02 (64tass)
; Relire une ligne déjà affichée à l'écran (groupe 2, fonction 3).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<ligne
ldx #>ligne
jsr ecrire
jsr WaitMessage
lda #2
ldx #13 ; Cursor Position
jsr appel
ldy ControlPort+5 ; ligne du curseur
dey ; remonter sur la ligne affichée
jsr WaitMessage
stz ControlPort+4
sty ControlPort+5
lda #2
ldx #7 ; Set Cursor Pos
jsr appel
jsr WaitMessage
lda #<tampon
sta ControlPort+4 ; P0-P1 : tampon de 256 octets
lda #>tampon
sta ControlPort+5
lda #2
ldx #3 ; fonction 3 : Read Line
jsr appel
lda #<relu
ldx #>relu
jsr ecrire
ldx #0
_txt: cpx tampon ; longueur
beq _fin
lda tampon+1,x
jsr WriteCharacter
inx
bne _txt
_fin: lda #13
jmp WriteCharacter
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
ligne: .text "Bonjour tout le monde", 13, 0
relu: .text "Relu : ", 0
tampon: .fill 256Bonjour tout le monde
Relu : Bonjour tout le monde2,4 Define Hotkey Officiel
Associe un texte à une touche de fonction F1 à F10 : l'appui sur la touche le tape comme au clavier.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro de la touche, 1 (F1) à 10 (F10) |
P2-P3 | addr | adresse du texte, précédé de sa longueur |
Sorties : aucune.
F11 et F12 ne peuvent pas être définies. L'adresse du texte est en P2-P3 (P1 n'est pas utilisé). En NeoBASIC, fkey n, "texte" fait le même appel. En Mad Pascal 1.7.8, NeoDefineHotkey range l'adresse en P0-P1, ce qui écrase le numéro de touche : l'appel échoue (erreur 1) ; l'exemple fait l'appel directement.
Mots-clés NeoBASIC qui font cet appel : fkey
Texte de la documentation du firmware (anglais)
Define the function key F1..F10 specified in Parameter:0 as 1..10 to emit the length-prefixed string stored at the memory location specified in Parameters:2,3.
F11 and F12 cannot currently be defined.
C (llvm-mos)
/* Associer un texte à la touche F1, puis lister les touches (groupe 2, fonctions 4 et 8). */
#include <stdio.h>
#include <neo/api.h>
int main(void) {
neo_console_define_hotkey(1, "Bonjour"); /* F1 */
neo_console_list_hotkeys(); /* 2,8 : afficher les définitions */
return 0;
}F1 : "Bonjour"
F8 : ""Mad Pascal
// Associer un texte à la touche F1, puis lister les touches (groupe 2, fonctions 4 et 8).
// NeoDefineHotkey (Mad Pascal 1.7.8) range l'adresse en P0-P1 et écrase la touche : appel direct.
program hotkey;
uses crt, neo6502;
var texte: string[32]; // chaîne Pascal : longueur puis texte
begin
texte := 'Bonjour';
NeoWaitMessage;
NeoMessage.params[0] := 1; // P0 : F1
wordParams[1] := word(@texte); // P2-P3 : adresse du texte
NeoSendMessage(2, 4); // Define Hotkey
NeoWaitMessage;
NeoShowHotkeys; // 2,8 : afficher les définitions
NeoWaitMessage;
end.F1 : "Bonjour"
F8 : ""NeoBASIC
10 ' Associer un texte a la touche F1, puis lister les touches (groupe 2, fonctions 4 et 8)
20 fkey 1, "Bonjour"
30 fkeyF1 : "Bonjour"Assembleur 65C02 (64tass)
; Associer un texte à la touche F1, puis lister les touches (groupe 2, fonctions 4 et 8).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #1
sta ControlPort+4 ; P0 : F1
lda #<texte
sta ControlPort+6 ; P2-P3 : adresse du texte
lda #>texte
sta ControlPort+7
lda #2
ldx #4 ; fonction 4 : Define Hotkey
jsr appel
jsr WaitMessage
lda #2
ldx #8 ; fonction 8 : List Hotkeys
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
texte: .byte 7 ; longueur
.text "Bonjour"F1 : "Bonjour"
F8 : ""2,5 Define Character Officiel
Redessine l'un des caractères 192 à 255 de la police, ligne par ligne (6 colonnes × 7 lignes).
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | code du caractère (192 à 255) |
P1-P7 | 7 × uint8 | les 7 lignes du dessin, de haut en bas ; bits 0 à 5 = colonnes |
Sorties : aucune.
Les caractères redéfinis restent en place jusqu'à la réinitialisation. En NeoBASIC, defchr c, l1, …, l7 fait le même appel.
Mots-clés NeoBASIC qui font cet appel : defchr
Texte de la documentation du firmware (anglais)
Define a font character specified in Parameter:0 within the range of 192..255. Fill bits 0..5 (columns) of Parameters:1..7 (rows) with the character bitmap.
C (llvm-mos)
/* Dessiner un visage souriant dans le caractère 192 (groupe 2, fonction 5). */
#include <stdio.h>
#include <neo/api.h>
static const uint8_t visage[7] = { 0x1E, 0x21, 0x2D, 0x21, 0x2D, 0x33, 0x1E }; /* bits 0-5 */
int main(void) {
neo_console_define_char(192, visage);
printf("Caractere 192 redefini : %c\n", 192);
return 0;
}Caractere 192 redefini : .Mad Pascal
// Dessiner un visage souriant dans le caractère 192 (groupe 2, fonction 5).
program defchar;
uses crt, neo6502;
const visage: array[0..6] of byte = ($1E, $21, $2D, $21, $2D, $33, $1E); // bits 0-5
begin
NeoSetChar(192, @visage);
NeoWaitMessage;
writeln('Caractere 192 redefini : ', chr(192));
end.Caractere 192 redefini : .NeoBASIC
10 ' Dessiner un visage souriant dans le caractere 192 (groupe 2, fonction 5)
20 defchr 192, $1e, $21, $2d, $21, $2d, $33, $1e
30 print "Caractere 192 redefini : ";chr$(192)Caractere 192 redefini : .Assembleur 65C02 (64tass)
; Dessiner un visage souriant dans le caractère 192 (groupe 2, fonction 5).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #192
sta ControlPort+4 ; P0 : le caractère
ldx #6
_copie: lda visage,x ; P1-P7 : les 7 lignes
sta ControlPort+5,x
dex
bpl _copie
lda #2
ldx #5 ; fonction 5 : Define Character
jsr appel
lda #<message
ldx #>message
jsr ecrire
lda #192
jsr WriteCharacter
lda #13
jmp WriteCharacter
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
visage: .byte $1E, $21, $2D, $21, $2D, $33, $1E
message: .text "Caractere 192 redefini : ", 0Caractere 192 redefini : .2,6 Write Character Officiel
Écrit un caractère, ou exécute un code de contrôle, à la position du curseur.
| Octets | Type | Rôle |
|---|---|---|
P0 | char | 32-126 et $A0-$FF : caractère affiché ; $80-$8F : couleur du texte ; $90-$9F : couleur du fond ; codes de contrôle : 8 retour arrière, 9 tabulation, 10 ligne suivante, 12 effacer l'écran, 13 retour à la ligne, 20 curseur en haut à gauche, 1/4/19/23 curseur gauche/droite/bas/haut, 24 inverser le caractère sous le curseur, 26 supprimer |
Sorties : aucune.
C'est la routine WriteCharacter du noyau ($FFF1) ; les codes viennent de CONWrite dans le firmware.
Texte de la documentation du firmware (anglais)
Write the character specified in Parameter:0 to the console at the cursor position. Refer to Section "Console Codes" for details.
C (llvm-mos)
/* Écrire un texte, en changeant la couleur (groupe 2, fonction 6). */
#include <neo/api.h>
int main(void) {
const char *texte = "\x83" "Bonjour" "\x87" "\r"; /* $83 : couleur 3, $87 : couleur 7 */
while (*texte)
neo_console_write_char(*texte++);
return 0;
}BonjourMad Pascal
// Écrire un texte, en changeant la couleur (groupe 2, fonction 6).
program ecrire6;
uses crt, neo6502;
var texte: string[16];
i: byte;
begin
texte := #$83'Bonjour'#$87#13; // $83 : couleur 3, $87 : couleur 7, retour à la ligne
for i := 1 to length(texte) do
begin
NeoWaitMessage;
NeoMessage.params[0] := ord(texte[i]);
NeoSendMessage(2, 6); // Write Character
end;
NeoWaitMessage;
end.BonjourNeoBASIC
10 ' Ecrire un texte, en changeant la couleur (groupe 2, fonction 6)
20 t$ = chr$($83) + "Bonjour" + chr$($87) + chr$(13) : ' $83 : couleur 3, $87 : couleur 7
30 for i = 1 to len(t$)
40 while peek($ff00) : wend
50 poke $ff04, asc(mid$(t$, i, 1)) : poke $ff01, 6 : poke $ff00, 2
60 next i
70 while peek($ff00) : wendBonjourAssembleur 65C02 (64tass)
; Écrire un texte, en changeant la couleur (groupe 2, fonction 6).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #0
_suiv: lda texte,x
beq _fin
jsr WaitMessage
sta ControlPort+4 ; P0 : caractère ou code
phx
lda #2
ldx #6 ; fonction 6 : Write Character
jsr appel
plx
inx
bne _suiv
_fin: rts
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
texte: .byte $83 ; couleur 3
.text "Bonjour"
.byte $87, 13, 0 ; couleur 7, retour à la ligneBonjour2,7 Set Cursor Pos Officiel
Place le curseur sur une case de l'écran (colonne, ligne).
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | colonne (0 = gauche) |
P1 | uint8 | ligne (0 = haut) |
Sorties : aucune.
En NeoBASIC, cursor x, y fait le même appel. La taille de l'écran est donnée par 2,9.
Mots-clés NeoBASIC qui font cet appel : cursor
Texte de la documentation du firmware (anglais)
Move the cursor to the screen character cell Parameter:0 (X), Parameter:1 (Y).
C (llvm-mos)
/* Écrire en colonne 10 de la ligne suivante (groupe 2, fonction 7). */
#include <stdio.h>
#include <neo/api.h>
int main(void) {
uint8_t x, y;
neo_console_cursor_pos(&x, &y); /* 2,13 : où est le curseur */
neo_console_set_cursor_pos(10, y); /* colonne 10, même ligne */
printf("Ici\n");
return 0;
} IciMad Pascal
// Écrire en colonne 10 de la ligne courante (groupe 2, fonction 7).
program curseur;
uses crt, neo6502;
var x, y: byte;
begin
NeoGetCursorPos(x, y); // 2,13 : où est le curseur
NeoWaitMessage;
NeoMessage.params[0] := 10; // colonne
NeoMessage.params[1] := y; // ligne
NeoSendMessage(2, 7); // Set Cursor Pos
NeoWaitMessage;
writeln('Ici');
end. IciNeoBASIC
10 ' Ecrire en colonne 10 de la ligne courante (groupe 2, fonction 7)
20 while peek($ff00) : wend
30 poke $ff01, 13 : poke $ff00, 2
40 while peek($ff00) : wend : y = peek($ff05)
50 cursor 10, y
60 print "Ici" IciAssembleur 65C02 (64tass)
; Écrire en colonne 10 de la ligne courante (groupe 2, fonction 7).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #2
ldx #13 ; Cursor Position
jsr appel
ldy ControlPort+5 ; ligne actuelle
jsr WaitMessage
lda #10
sta ControlPort+4 ; P0 : colonne 10
sty ControlPort+5 ; P1 : même ligne
lda #2
ldx #7 ; fonction 7 : Set Cursor Pos
jsr appel
lda #<ici
ldx #>ici
jmp ecrire
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
ici: .text "Ici", 13, 0 Ici2,8 List Hotkeys Officiel
Affiche les textes associés aux touches de fonction (voir 2,4).
Entrées : aucune.
Sorties : aucune.
En NeoBASIC, fkey sans argument fait le même appel.
Mots-clés NeoBASIC qui font cet appel : fkey
Texte de la documentation du firmware (anglais)
Display the current function key definitions.
C (llvm-mos)
/* Lister les touches de fonction après avoir défini F1 (groupe 2, fonction 8). */
#include <neo/api.h>
int main(void) {
neo_console_define_hotkey(1, "Liste"); /* 2,4 */
neo_console_list_hotkeys(); /* List Hotkeys */
return 0;
}F1 : "Liste"
F8 : ""Mad Pascal
// Lister les touches de fonction après avoir défini F1 (groupe 2, fonction 8).
program listkeys;
uses crt, neo6502;
var texte: string[16];
begin
texte := 'Liste';
NeoWaitMessage;
NeoMessage.params[0] := 1; // 2,4 : F1 ...
wordParams[1] := word(@texte); // ... texte en P2-P3
NeoSendMessage(2, 4);
NeoWaitMessage;
NeoShowHotkeys; // List Hotkeys
NeoWaitMessage;
end.F1 : "Liste"
F8 : ""NeoBASIC
10 ' Lister les touches de fonction apres avoir defini F1 (groupe 2, fonction 8)
20 fkey 1, "Liste"
30 while peek($ff00) : wend
40 poke $ff01, 8 : poke $ff00, 2
50 while peek($ff00) : wendF1 : "Liste"Assembleur 65C02 (64tass)
; Lister les touches de fonction après avoir défini F1 (groupe 2, fonction 8).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #1
sta ControlPort+4 ; F1
lda #<texte
sta ControlPort+6
lda #>texte
sta ControlPort+7
lda #2
ldx #4 ; 2,4 : Define Hotkey
jsr appel
jsr WaitMessage
lda #2
ldx #8 ; fonction 8 : List Hotkeys
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
texte: .byte 5
.text "Liste"F1 : "Liste"
F8 : ""2,9 Screen Size Officiel
Donne la taille de la console en caractères.
Entrées : aucune.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | hauteur (nombre de lignes) |
P1 | uint8 | largeur (nombre de colonnes) |
Attention à l'ordre : la hauteur vient d'abord. La taille dépend du mode vidéo (5,9).
Texte de la documentation du firmware (anglais)
Returns the console size in characters, in Parameter:0 (height) and Parameter:1 (width).
C (llvm-mos)
/* Taille de la console (groupe 2, fonction 9). */
#include <stdio.h>
#include <neo/api.h>
int main(void) {
uint8_t largeur, hauteur;
neo_console_screen_size(&largeur, &hauteur);
printf("Console : %u colonnes, %u lignes\n", largeur, hauteur);
return 0;
}Console : 53 colonnes, 30 lignesMad Pascal
// Taille de la console (groupe 2, fonction 9).
program taille;
uses crt, neo6502;
var hauteur, largeur: byte;
begin
NeoGetScreenSize(hauteur, largeur);
writeln('Console : ', largeur, ' colonnes, ', hauteur, ' lignes');
end.Console : 30 colonnes, 53 lignesNeoBASIC
10 ' Taille de la console (groupe 2, fonction 9)
20 ' lire les resultats dans des variables juste apres l'appel : print reutilise la boite aux lettres
30 while peek($ff00) : wend
40 poke $ff01, 9 : poke $ff00, 2
50 while peek($ff00) : wend : h = peek($ff04) : l = peek($ff05)
60 print "Console : ";l;" colonnes, ";h;" lignes"Console : 30 colonnes, 53 lignesAssembleur 65C02 (64tass)
; Taille de la console (groupe 2, fonction 9).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #2
ldx #9 ; fonction 9 : Screen Size
jsr appel
lda ControlPort+4 ; P0 : hauteur
sta hauteur
lda ControlPort+5 ; P1 : largeur
sta largeur
lda #<m1
ldx #>m1
jsr ecrire
lda largeur
jsr decimal
lda #<m2
ldx #>m2
jsr ecrire
lda hauteur
jsr decimal
lda #<m3
ldx #>m3
jmp ecrire
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
hauteur: .byte 0
largeur: .byte 0
m1: .text "Console : ", 0
m2: .text " colonnes, ", 0
m3: .text " lignes", 13, 0Console : 30 colonnes, 53 lignes2,10 Insert Line Officiel
Insère une ligne vide à la ligne donnée ; les lignes suivantes descendent, la dernière de l'écran est perdue.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro de la ligne (0 = haut) |
Sorties : aucune.
Fonction de service de la console (l'éditeur s'en sert) ; la documentation du firmware déconseille de l'utiliser directement.
Texte de la documentation du firmware (anglais)
This is a support function which inserts a blank line in the console and should not be used.
C (llvm-mos)
/* Insérer une ligne vide entre A et B (groupe 2, fonction 10). */
#include <stdio.h>
#include <neo6502.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)
;
}
int main(void) {
libre();
api(2, 12); /* écran vide : les lignes sont en haut */
printf("Ligne A\nLigne B\nLigne C\n");
libre();
api(2, 13); /* Cursor Position */
uint8_t y = ControlPort.params[1]; /* ligne sous « Ligne C » */
libre();
ControlPort.params[0] = y - 2; /* la ligne de « Ligne B » */
api(2, 10); /* Insert Line */
libre();
ControlPort.params[0] = 0;
ControlPort.params[1] = y + 1; /* sous les lignes décalées */
api(2, 7);
return 0;
}Ligne A
Ligne B
Ligne CMad Pascal
// Insérer une ligne vide entre A et B (groupe 2, fonction 10).
program insline;
uses crt, neo6502;
var x, y: byte;
begin
NeoSendMessage(2, 12); // écran vide : les lignes sont en haut
NeoWaitMessage;
writeln('Ligne A'); writeln('Ligne B'); writeln('Ligne C');
NeoGetCursorPos(x, y); // ligne sous « Ligne C »
NeoWaitMessage;
NeoMessage.params[0] := y - 2; // la ligne de « Ligne B »
NeoSendMessage(2, 10); // Insert Line
NeoWaitMessage;
NeoMessage.params[0] := 0;
NeoMessage.params[1] := y + 1; // sous les lignes décalées
NeoSendMessage(2, 7);
NeoWaitMessage;
end.Ligne A
Ligne B
Ligne CNeoBASIC
10 ' Inserer une ligne vide entre A et B (groupe 2, fonction 10)
15 while peek($ff00) : wend : poke $ff01, 12 : poke $ff00, 2 : ' ecran vide
20 print "Ligne A" : print "Ligne B" : print "Ligne C"
30 while peek($ff00) : wend
40 poke $ff01, 13 : poke $ff00, 2
50 while peek($ff00) : wend : y = peek($ff05)
60 poke $ff04, y - 2 : poke $ff01, 10 : poke $ff00, 2
70 while peek($ff00) : wend
80 cursor 0, y + 1Ligne A
Ligne B
Ligne CAssembleur 65C02 (64tass)
; Insérer une ligne vide entre A et B (groupe 2, fonction 10).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #2
ldx #12 ; écran vide : les lignes sont en haut
jsr appel
lda #<lignes
ldx #>lignes
jsr ecrire
jsr WaitMessage
lda #2
ldx #13 ; Cursor Position
jsr appel
lda ControlPort+5 ; ligne sous « Ligne C »
sta posy
jsr WaitMessage
sec
sbc #2
sta ControlPort+4 ; P0 : la ligne de « Ligne B »
lda #2
ldx #10 ; fonction 10 : Insert Line
jsr appel
jsr WaitMessage
stz ControlPort+4
lda posy
inc a
sta ControlPort+5 ; sous les lignes décalées
lda #2
ldx #7
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
posy: .byte 0
lignes: .text "Ligne A", 13, "Ligne B", 13, "Ligne C", 13, 0Ligne A
Ligne B
Ligne C2,11 Delete Line Officiel
Supprime la ligne donnée ; les lignes suivantes remontent, une ligne vide apparaît en bas de l'écran.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro de la ligne (0 = haut) |
Sorties : aucune.
Fonction de service de la console (l'éditeur s'en sert) ; la documentation du firmware déconseille de l'utiliser directement.
Texte de la documentation du firmware (anglais)
This is a support function which deletes a line in the console and should not be used.
C (llvm-mos)
/* Supprimer la ligne « Ligne B » (groupe 2, fonction 11). */
#include <stdio.h>
#include <neo6502.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)
;
}
int main(void) {
libre();
api(2, 12); /* écran vide : les lignes sont en haut */
printf("Ligne A\nLigne B\nLigne C\n");
libre();
api(2, 13); /* Cursor Position */
uint8_t y = ControlPort.params[1];
libre();
ControlPort.params[0] = y - 2; /* la ligne de « Ligne B » */
api(2, 11); /* Delete Line */
return 0;
}Ligne A
Ligne CMad Pascal
// Supprimer la ligne « Ligne B » (groupe 2, fonction 11).
program delline;
uses crt, neo6502;
var x, y: byte;
begin
NeoSendMessage(2, 12); // écran vide : les lignes sont en haut
NeoWaitMessage;
writeln('Ligne A'); writeln('Ligne B'); writeln('Ligne C');
NeoGetCursorPos(x, y);
NeoWaitMessage;
NeoMessage.params[0] := y - 2; // la ligne de « Ligne B »
NeoSendMessage(2, 11); // Delete Line
NeoWaitMessage;
end.Ligne A
Ligne CNeoBASIC
10 ' Supprimer la ligne "Ligne B" (groupe 2, fonction 11)
15 while peek($ff00) : wend : poke $ff01, 12 : poke $ff00, 2 : ' ecran vide
20 print "Ligne A" : print "Ligne B" : print "Ligne C"
30 while peek($ff00) : wend
40 poke $ff01, 13 : poke $ff00, 2
50 while peek($ff00) : wend : y = peek($ff05)
60 poke $ff04, y - 2 : poke $ff01, 11 : poke $ff00, 2
70 while peek($ff00) : wendLigne A
Ligne CAssembleur 65C02 (64tass)
; Supprimer la ligne « Ligne B » (groupe 2, fonction 11).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #2
ldx #12 ; écran vide : les lignes sont en haut
jsr appel
lda #<lignes
ldx #>lignes
jsr ecrire
jsr WaitMessage
lda #2
ldx #13 ; Cursor Position
jsr appel
lda ControlPort+5
jsr WaitMessage
sec
sbc #2
sta ControlPort+4 ; P0 : la ligne de « Ligne B »
lda #2
ldx #11 ; fonction 11 : Delete Line
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
lignes: .text "Ligne A", 13, "Ligne B", 13, "Ligne C", 13, 0Ligne A
Ligne C2,12 Clear Screen Officiel
Efface l'écran de la console et replace le curseur en haut à gauche.
Entrées : aucune.
Sorties : aucune.
Le code de contrôle 12 envoyé par 2,6 a le même effet. La visibilité du curseur (2,19) est rétablie.
Texte de la documentation du firmware (anglais)
Clears the screen.
C (llvm-mos)
/* Effacer l'écran (groupe 2, fonction 12). */
#include <stdio.h>
#include <neo/api.h>
int main(void) {
printf("Ce texte va disparaitre\n");
neo_console_clear_screen();
printf("Ecran efface\n");
return 0;
}Ecran effaceMad Pascal
// Effacer l'écran (groupe 2, fonction 12).
program cls;
uses crt, neo6502;
begin
writeln('Ce texte va disparaitre');
NeoSendMessage(2, 12); // Clear Screen
NeoWaitMessage;
writeln('Ecran efface');
end.Ecran effaceNeoBASIC
10 ' Effacer l'ecran (groupe 2, fonction 12)
20 print "Ce texte va disparaitre"
30 while peek($ff00) : wend
40 poke $ff01, 12 : poke $ff00, 2
50 while peek($ff00) : wend
60 print "Ecran efface"Ecran effaceAssembleur 65C02 (64tass)
; Effacer l'écran (groupe 2, fonction 12).
.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 #<avant
ldx #>avant
jsr ecrire
jsr WaitMessage
lda #2
ldx #12 ; fonction 12 : Clear Screen
jsr appel
lda #<apres
ldx #>apres
jmp ecrire
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
avant: .text "Ce texte va disparaitre", 13, 0
apres: .text "Ecran efface", 13, 0Ecran efface2,13 Cursor Position Officiel
Donne la position du curseur (colonne, ligne).
Entrées : aucune.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | colonne |
P1 | uint8 | ligne |
Mots-clés NeoBASIC qui font cet appel : print
Texte de la documentation du firmware (anglais)
Returns the current screen character cell of the cursor in Parameter:0 (X), Parameter:1 (Y).
C (llvm-mos)
/* Position du curseur après un texte de 7 caractères (groupe 2, fonction 13). */
#include <stdio.h>
#include <neo/api.h>
int main(void) {
uint8_t x, y;
printf("Bonjour"); /* 7 caractères, sans retour à la ligne */
neo_console_cursor_pos(&x, &y);
printf("\nCurseur : colonne %u, ligne %u\n", x, y);
return 0;
}Bonjour
Curseur : colonne 7, ligne 27Mad Pascal
// Position du curseur après un texte de 7 caractères (groupe 2, fonction 13).
program position;
uses crt, neo6502;
var x, y: byte;
begin
write('Bonjour'); // 7 caractères, sans retour à la ligne
NeoGetCursorPos(x, y);
writeln;
writeln('Curseur : colonne ', x, ', ligne ', y);
end.Bonjour
Curseur : colonne 7, ligne 27NeoBASIC
10 ' Position du curseur apres un texte de 7 caracteres (groupe 2, fonction 13)
20 ' lire les resultats dans des variables juste apres l'appel : print reutilise la boite aux lettres
30 print "Bonjour";
40 while peek($ff00) : wend
50 poke $ff01, 13 : poke $ff00, 2
60 while peek($ff00) : wend : x = peek($ff04) : y = peek($ff05)
70 print
80 print "Curseur : colonne ";x;", ligne ";yBonjour
Curseur : colonne 7, ligne 29Assembleur 65C02 (64tass)
; Position du curseur après un texte de 7 caractères (groupe 2, fonction 13).
.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 #<texte
ldx #>texte
jsr ecrire
jsr WaitMessage
lda #2
ldx #13 ; fonction 13 : Cursor Position
jsr appel
lda ControlPort+4 ; recopier avant d'afficher
sta posx
lda ControlPort+5
sta posy
lda #<m1
ldx #>m1
jsr ecrire
lda posx
jsr decimal
lda #<m2
ldx #>m2
jsr ecrire
lda posy
jsr decimal
lda #13
jmp WriteCharacter
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
posx: .byte 0
posy: .byte 0
texte: .text "Bonjour", 0
m1: .text 13, "Curseur : colonne ", 0
m2: .text ", ligne ", 0Bonjour
Curseur : colonne 7, ligne 272,14 Clear Region Officiel
Efface un rectangle de l'écran, bornes comprises.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | colonne de départ |
P1 | uint8 | ligne de départ |
P2 | uint8 | colonne de fin (comprise) |
P3 | uint8 | ligne de fin (comprise) |
Sorties : aucune.
Les bornes sont ramenées dans l'écran ; le rectangle est rempli d'espaces aux couleurs en cours.
Texte de la documentation du firmware (anglais)
Erase all characters within the rectangular region specified in Parameters:0,1 (begin X,Y) and Parameters:2,3 (end X,Y).
C (llvm-mos)
/* Creuser les colonnes 2 à 5 de trois lignes (groupe 2, fonction 14). */
#include <stdio.h>
#include <neo/api.h>
int main(void) {
uint8_t x, y;
printf("XXXXXXXXXX\nXXXXXXXXXX\nXXXXXXXXXX\n");
neo_console_cursor_pos(&x, &y);
neo_console_clear_region(2, y - 3, 5, y - 1); /* colonnes 2 à 5 comprises */
return 0;
}XX XXXX
XX XXXX
XX XXXXMad Pascal
// Creuser les colonnes 2 à 5 de trois lignes (groupe 2, fonction 14).
program region;
uses crt, neo6502;
var x, y: byte;
begin
writeln('XXXXXXXXXX'); writeln('XXXXXXXXXX'); writeln('XXXXXXXXXX');
NeoGetCursorPos(x, y);
NeoClearRegion(2, y - 3, 5, y - 1); // colonnes 2 à 5 comprises
NeoWaitMessage;
end.XX XXXX
XX XXXX
XX XXXXNeoBASIC
10 ' Creuser les colonnes 2 a 5 de trois lignes (groupe 2, fonction 14)
20 for i = 1 to 3 : print "XXXXXXXXXX" : next i
30 while peek($ff00) : wend
40 poke $ff01, 13 : poke $ff00, 2
50 while peek($ff00) : wend : y = peek($ff05)
60 poke $ff04, 2 : poke $ff05, y - 3 : poke $ff06, 5 : poke $ff07, y - 1 : poke $ff01, 14 : poke $ff00, 2
70 while peek($ff00) : wendXX XXXX
XX XXXX
XX XXXXAssembleur 65C02 (64tass)
; Creuser les colonnes 2 à 5 de trois lignes (groupe 2, fonction 14).
.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 #<lignes
ldx #>lignes
jsr ecrire
jsr WaitMessage
lda #2
ldx #13 ; Cursor Position
jsr appel
ldy ControlPort+5 ; ligne sous le bloc
jsr WaitMessage
lda #2
sta ControlPort+4 ; P0 : colonne 2
tya
sec
sbc #3
sta ControlPort+5 ; P1 : première ligne du bloc
lda #5
sta ControlPort+6 ; P2 : colonne 5 (comprise)
dey
sty ControlPort+7 ; P3 : dernière ligne du bloc
lda #2
ldx #14 ; fonction 14 : Clear Region
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
lignes: .text "XXXXXXXXXX", 13, "XXXXXXXXXX", 13, "XXXXXXXXXX", 13, 0XX XXXX
XX XXXX
XX XXXX2,15 Set Text Color Officiel
Choisit la couleur du texte et celle du fond pour les caractères écrits ensuite.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | couleur du texte (0 à 15) |
P1 | uint8 | couleur du fond (0 à 15) |
Sorties : aucune.
Les codes $80-$8F et $90-$9F écrits par 2,6 font la même chose caractère par caractère. 2,18 relit les couleurs en cours, pour les rétablir.
Texte de la documentation du firmware (anglais)
Sets the foreground colour to Parameter:0 and the background colour to Parameter:1.
C (llvm-mos)
/* Écrire en couleur, puis rétablir les couleurs (groupe 2, fonctions 15 et 18). */
#include <stdio.h>
#include <neo/api.h>
int main(void) {
uint8_t encre, papier;
neo_console_get_text_color(&encre, &papier); /* 2,18 : couleurs en cours */
neo_console_set_text_color(3, 1); /* texte 3 sur fond 1 */
printf("Texte en couleur");
neo_console_set_text_color(encre, papier); /* rétablir */
printf("\n");
return 0;
}Texte en couleurMad Pascal
// Écrire en couleur, puis rétablir les couleurs (groupe 2, fonctions 15 et 18).
program couleur;
uses crt, neo6502;
var encre, papier: byte;
begin
NeoSendMessage(2, 18); // Read Ink/Paper Colours
NeoWaitMessage;
encre := NeoMessage.params[0];
papier := NeoMessage.params[1];
NeoSetTextColor(3, 1); // texte 3 sur fond 1
NeoWaitMessage;
write('Texte en couleur');
NeoSetTextColor(encre, papier); // rétablir
NeoWaitMessage;
writeln;
end.Texte en couleurNeoBASIC
10 ' Ecrire en couleur, puis retablir les couleurs (groupe 2, fonctions 15 et 18)
20 while peek($ff00) : wend
30 poke $ff01, 18 : poke $ff00, 2
40 while peek($ff00) : wend : e = peek($ff04) : p = peek($ff05)
50 poke $ff04, 3 : poke $ff05, 1 : poke $ff01, 15 : poke $ff00, 2
60 while peek($ff00) : wend
70 print "Texte en couleur";
80 while peek($ff00) : wend
90 poke $ff04, e : poke $ff05, p : poke $ff01, 15 : poke $ff00, 2
100 while peek($ff00) : wend
110 printTexte en couleurAssembleur 65C02 (64tass)
; Écrire en couleur, puis rétablir les couleurs (groupe 2, fonctions 15 et 18).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #2
ldx #18 ; 2,18 : couleurs en cours
jsr appel
lda ControlPort+4
sta encre
lda ControlPort+5
sta papier
jsr WaitMessage
lda #3
sta ControlPort+4 ; P0 : texte 3
lda #1
sta ControlPort+5 ; P1 : fond 1
lda #2
ldx #15 ; fonction 15 : Set Text Color
jsr appel
lda #<texte
ldx #>texte
jsr ecrire
jsr WaitMessage
lda encre ; rétablir
sta ControlPort+4
lda papier
sta ControlPort+5
lda #2
ldx #15
jsr appel
lda #13
jmp WriteCharacter
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
encre: .byte 0
papier: .byte 0
texte: .text "Texte en couleur", 0Texte en couleur2,16 Cursor Inverse Officiel
Inverse les couleurs (texte et fond) de la case du curseur ; un second appel les rétablit.
Entrées : aucune.
Sorties : aucune.
Fonction de service (clignotement du curseur) ; la documentation du firmware déconseille de l'utiliser.
Texte de la documentation du firmware (anglais)
Toggles the cursor colour between normal and inverse (ie: swaps FG and BG colors). This should not be used.
C (llvm-mos)
/* Inverser la case du curseur, puis la rétablir (groupe 2, fonction 16). */
#include <stdio.h>
#include <neo6502.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)
;
}
int main(void) {
libre();
api(2, 16); /* Cursor Inverse */
libre();
api(2, 16); /* et retour */
printf("Case du curseur inversee deux fois\n");
return 0;
}Case du curseur inversee deux foisMad Pascal
// Inverser la case du curseur, puis la rétablir (groupe 2, fonction 16).
program inverse;
uses crt, neo6502;
begin
NeoCursorInverse; // Cursor Inverse
NeoWaitMessage;
NeoCursorInverse; // et retour
NeoWaitMessage;
writeln('Case du curseur inversee deux fois');
end.Case du curseur inversee deux foisNeoBASIC
10 ' Inverser la case du curseur, puis la retablir (groupe 2, fonction 16)
20 for i = 1 to 2
30 while peek($ff00) : wend
40 poke $ff01, 16 : poke $ff00, 2
50 next i
60 while peek($ff00) : wend
70 print "Case du curseur inversee deux fois"Case du curseur inversee deux foisAssembleur 65C02 (64tass)
; Inverser la case du curseur, puis la rétablir (groupe 2, fonction 16).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #2
ldx #16 ; fonction 16 : Cursor Inverse
jsr appel
jsr WaitMessage
lda #2
ldx #16 ; et retour
jsr appel
lda #<texte
ldx #>texte
jmp ecrire
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
texte: .text "Case du curseur inversee deux fois", 13, 0Case du curseur inversee deux fois2,17 Tab() implementation Officiel
Écrit des espaces jusqu'à ce que le curseur atteigne la colonne donnée (sert au tab() de NeoBASIC).
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | colonne à atteindre |
Sorties : aucune.
Si le curseur est déjà au-delà, rien n'est écrit. En NeoBASIC, tab(n) dans un print fait le même appel.
Mots-clés NeoBASIC qui font cet appel : tab()
Texte de la documentation du firmware (anglais)
Internal helper.
C (llvm-mos)
/* Aligner B en colonne 10 (groupe 2, fonction 17). */
#include <stdio.h>
#include <neo6502.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)
;
}
int main(void) {
printf("A");
libre();
ControlPort.params[0] = 10; /* colonne à atteindre */
api(2, 17); /* Tab */
printf("B\n");
return 0;
}A BMad Pascal
// Aligner B en colonne 10 (groupe 2, fonction 17).
program tab;
uses crt, neo6502;
begin
write('A');
NeoWaitMessage;
NeoMessage.params[0] := 10; // colonne à atteindre
NeoSendMessage(2, 17); // Tab
NeoWaitMessage;
writeln('B');
end.A BNeoBASIC
10 ' Aligner B en colonne 10 (groupe 2, fonction 17)
20 print "A";tab(10);"B"A BAssembleur 65C02 (64tass)
; Aligner B en colonne 10 (groupe 2, fonction 17).
.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 #'A'
jsr WriteCharacter
jsr WaitMessage
lda #10
sta ControlPort+4 ; P0 : colonne à atteindre
lda #2
ldx #17 ; fonction 17 : Tab
jsr appel
lda #'B'
jsr WriteCharacter
lda #13
jmp WriteCharacter
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0A B2,18 Read Ink/Paper Colours Officiel
Donne les couleurs en cours du texte (encre) et du fond (papier).
Entrées : aucune.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | couleur du texte |
P1 | uint8 | couleur du fond |
Texte de la documentation du firmware (anglais)
Read the ink/paper colours into Param[0] and Param[1]
C (llvm-mos)
/* Couleurs en cours (groupe 2, fonction 18). */
#include <stdio.h>
#include <neo/api.h>
int main(void) {
uint8_t encre, papier;
neo_console_get_text_color(&encre, &papier);
printf("Encre : %u, papier : %u\n", encre, papier);
return 0;
}Encre : 2, papier : 0Mad Pascal
// Couleurs en cours (groupe 2, fonction 18).
program couleurs;
uses crt, neo6502;
var encre, papier: byte;
begin
NeoSendMessage(2, 18); // Read Ink/Paper Colours
NeoWaitMessage;
encre := NeoMessage.params[0];
papier := NeoMessage.params[1];
writeln('Encre : ', encre, ', papier : ', papier);
end.Encre : 2, papier : 0NeoBASIC
10 ' Couleurs en cours (groupe 2, fonction 18)
20 ' lire les resultats dans des variables juste apres l'appel : print reutilise la boite aux lettres
30 while peek($ff00) : wend
40 poke $ff01, 18 : poke $ff00, 2
50 while peek($ff00) : wend : e = peek($ff04) : p = peek($ff05)
60 print "Encre : ";e;", papier : ";pEncre : 2, papier : 0Assembleur 65C02 (64tass)
; Couleurs en cours (groupe 2, fonction 18).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #2
ldx #18 ; fonction 18 : Read Ink/Paper Colours
jsr appel
lda ControlPort+4
sta encre
lda ControlPort+5
sta papier
lda #<m1
ldx #>m1
jsr ecrire
lda encre
jsr decimal
lda #<m2
ldx #>m2
jsr ecrire
lda papier
jsr decimal
lda #13
jmp WriteCharacter
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
encre: .byte 0
papier: .byte 0
m1: .text "Encre : ", 0
m2: .text ", papier : ", 0Encre : 2, papier : 02,19 Show/Hide Cursor Reversing Officiel
Montre ou cache le curseur clignotant.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | non nul : visible, 0 : caché |
Sorties : aucune.
Effacer l'écran (2,12) rend le curseur visible.
Texte de la documentation du firmware (anglais)
Set the cursor visibility to Param[0]. This is reset by clearing the screen.
C (llvm-mos)
/* Cacher le curseur, puis le réafficher (groupe 2, fonction 19). */
#include <stdio.h>
#include <neo/api.h>
int main(void) {
neo_console_set_cursor_visibility(0); /* caché */
neo_console_set_cursor_visibility(1); /* visible */
printf("Curseur cache puis reaffiche\n");
return 0;
}Curseur cache puis reafficheMad Pascal
// Cacher le curseur, puis le réafficher (groupe 2, fonction 19).
program visibilite;
uses crt, neo6502;
procedure curseur(visible: byte);
begin
NeoWaitMessage;
NeoMessage.params[0] := visible;
NeoSendMessage(2, 19); // Show/Hide Cursor
NeoWaitMessage;
end;
begin
curseur(0);
curseur(1);
writeln('Curseur cache puis reaffiche');
end.Curseur cache puis reafficheNeoBASIC
10 ' Cacher le curseur, puis le reafficher (groupe 2, fonction 19)
20 for v = 0 to 1
30 while peek($ff00) : wend
40 poke $ff04, v : poke $ff01, 19 : poke $ff00, 2
50 next v
60 while peek($ff00) : wend
70 print "Curseur cache puis reaffiche"Curseur cache puis reafficheAssembleur 65C02 (64tass)
; Cacher le curseur, puis le réafficher (groupe 2, fonction 19).
.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 #0 ; caché
jsr visible
lda #1 ; visible
jsr visible
lda #<texte
ldx #>texte
jmp ecrire
visible:
pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0 : visibilité
lda #2
ldx #19 ; fonction 19 : Show/Hide Cursor
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
texte: .text "Curseur cache puis reaffiche", 13, 0Curseur cache puis reaffiche2,20 Console Debug Echo Trinity
Recopie tout ce qui s'écrit sur la console vers le port de débogage (l'UART GP28/GP29 sur la carte) : un PC peut ainsi capter le texte de l'écran.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | 0 : arrêt ; 1 : caractères imprimables et Entrée (en CR LF) ; 2 : aussi les caractères $A0-$FF |
Sorties : aucune.
Dans les émulateurs, l'écho part sur la sortie d'erreur.
Texte de la documentation du firmware (anglais)
Parameter:0 non zero : every printable character written to the console (and Enter, as CR LF) is also sent to the debug port (UART GP28/GP29 on the board, stderr in the emulators) ; 2 also forwards the characters $A0-$FF. 0 stops the echo. Lets a PC capture the screen text of a real board over the serial link (Trinity T-20, F-92 of the fork).
C (llvm-mos)
/* Recopier la console vers le port de débogage le temps d'une ligne (groupe 2, fonction 20). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static void echo(uint8_t mode) {
libre();
ControlPort.params[0] = mode;
api(2, 20); /* Console Debug Echo */
}
int main(void) {
echo(1);
printf("Ce texte part aussi sur le port de debogage\n");
echo(0);
return 0;
}Ce texte part aussi sur le port de debogageMad Pascal
// Recopier la console vers le port de débogage le temps d'une ligne (groupe 2, fonction 20).
program echo;
uses crt, neo6502;
procedure echo(mode: byte);
begin
NeoWaitMessage;
NeoMessage.params[0] := mode;
NeoSendMessage(2, 20); // Console Debug Echo
NeoWaitMessage;
end;
begin
echo(1);
writeln('Ce texte part aussi sur le port de debogage');
echo(0);
end.Ce texte part aussi sur le port de debogageNeoBASIC
10 ' Recopier la console vers le port de debogage le temps d'une ligne (groupe 2, fonction 20)
20 while peek($ff00) : wend
30 poke $ff04, 1 : poke $ff01, 20 : poke $ff00, 2
40 while peek($ff00) : wend
50 print "Ce texte part aussi sur le port de debogage"
60 while peek($ff00) : wend
70 poke $ff04, 0 : poke $ff01, 20 : poke $ff00, 2
80 while peek($ff00) : wendCe texte part aussi sur le port de debogageAssembleur 65C02 (64tass)
; Recopier la console vers le port de débogage le temps d'une ligne (groupe 2, fonction 20).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #1
jsr echo
lda #<texte
ldx #>texte
jsr ecrire
lda #0
echo: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0 : mode d'écho
lda #2
ldx #20 ; fonction 20 : Console Debug Echo
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
texte: .text "Ce texte part aussi sur le port de debogage", 13, 0Ce texte part aussi sur le port de debogage2,21 Set Console Font Trinity
Remplace la police des caractères $20-$7F de la console par une police en RAM ; l'adresse 0 rétablit la police intégrée.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | 96 caractères de 8 octets (un octet par ligne, bit 7 = pixel de gauche), du $20 au $7F ; 0 : police intégrée |
P2-P3 | addr | 96 caractères de 14 octets pour les cases 9×14 du mode Hercules (1) ; 0 : garder la police 8×14 intégrée |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | non nul si la police dépasserait la fin de la mémoire |
La police est lue sur place à chaque rafraîchissement, sans copie : la garder intacte tant qu'elle est choisie. Toute la console est redessinée. Un changement de mode (5,9) ou un redémarrage rétablit la police intégrée. Les caractères $A0-$BF (symboles Latin-1) et $C0-$FF (2,5) ne changent pas.
Texte de la documentation du firmware (anglais)
Selects the font used by the console for the characters $20-$7F (Trinity T-20, F-95 of the fork). On input:
Parameters:0,1 is the address, in 6502 RAM, of 96 glyphs of 8 bytes (one byte per row, bit 7 = leftmost pixel ; the console draws the 6 leftmost columns in 6x8 cells and all 8 in 8x8 cells), in ASCII order from $20 to $7F ; $0000 restores the built in font.
Parameters:2,3 is likewise the address of 96 glyphs of 14 bytes (8 columns) used by the 9x14 cells of the Hercules mode 1 ; $0000 keeps the built in 8x14 font. Each address is checked and applied on its own.
The glyphs are read in place at every repaint (no copy) : the program must keep them intact while the font is selected. The whole console is repainted. Characters $A0-$BF keep the built in Latin-1 symbols and $C0-$FF the user defined characters (Function 2,5 ; Latin-1 letters by default). The built in font is restored by a mode change (5,9) and at reset. Sets the error flag if the glyphs would run past the end of memory.
C (llvm-mos)
/* Remplacer la police par des cadres, puis rétablir l'originale (groupe 2, fonction 21). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t police[96 * 8]; /* 96 caractères de 8 lignes */
static void choisir(uint16_t adresse) {
libre();
ControlPort.params[0] = adresse & 0xFF;
ControlPort.params[1] = adresse >> 8;
ControlPort.params[2] = 0; /* mode Hercules : police intégrée */
ControlPort.params[3] = 0;
api(2, 21); /* Set Console Font */
}
int main(void) {
static const uint8_t cadre[8] = { 0x00, 0xFC, 0x84, 0x84, 0x84, 0x84, 0xFC, 0x00 };
for (unsigned i = 0; i < sizeof police; i++)
police[i] = cadre[i % 8];
choisir((uint16_t)police);
printf("Police remplacee\n");
choisir(0); /* police intégrée */
printf("Police d'origine\n");
return 0;
}Police remplacee
Police d'origineMad Pascal
// Remplacer la police par des cadres, puis rétablir l'originale (groupe 2, fonction 21).
program police;
uses crt, neo6502;
const cadre: array[0..7] of byte = ($00, $FC, $84, $84, $84, $84, $FC, $00);
var fonte: array[0..767] of byte; // 96 caractères de 8 lignes
i: word;
procedure choisir(adresse: word);
begin
NeoWaitMessage;
wordParams[0] := adresse;
wordParams[1] := 0; // mode Hercules : police intégrée
NeoSendMessage(2, 21); // Set Console Font
NeoWaitMessage;
end;
begin
for i := 0 to 767 do fonte[i] := cadre[i and 7];
choisir(word(@fonte));
writeln('Police remplacee');
choisir(0); // police intégrée
writeln('Police d''origine');
end.Police remplacee
Police d'origineNeoBASIC
10 ' Remplacer la police par des cadres, puis retablir l'originale (groupe 2, fonction 21)
20 a = alloc(768)
30 for i = 0 to 95 : for r = 0 to 7 : read v : poke a + i * 8 + r, v : next r : restore : next i
40 data 0, $fc, $84, $84, $84, $84, $fc, 0
50 while peek($ff00) : wend
60 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff06, 0 : poke $ff07, 0 : poke $ff01, 21 : poke $ff00, 2
70 while peek($ff00) : wend
80 print "Police remplacee"
90 while peek($ff00) : wend
100 poke $ff04, 0 : poke $ff05, 0 : poke $ff06, 0 : poke $ff07, 0 : poke $ff01, 21 : poke $ff00, 2
110 while peek($ff00) : wend
120 print "Police d'origine"Police remplacee
Police d'origineAssembleur 65C02 (64tass)
; Remplacer la police par des cadres, puis rétablir l'originale (groupe 2, fonction 21).
.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
POLICE = $4000 ; 96 caractères de 8 lignes = 768 octets
start: lda #<POLICE ; remplir la police : le même cadre partout
sta ptr
lda #>POLICE
sta ptr+1
ldx #96
_car: ldy #7
_lig: lda cadre,y
sta (ptr),y
dey
bpl _lig
clc
lda ptr
adc #8
sta ptr
bcc _s
inc ptr+1
_s: dex
bne _car
lda #<POLICE
ldx #>POLICE
jsr choisir
lda #<m1
ldx #>m1
jsr ecrire
lda #0 ; police intégrée
tax
jsr choisir
lda #<m2
ldx #>m2
jmp ecrire
; A/X = adresse de la police (0 : intégrée).
choisir:
pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : police 8×8
stx ControlPort+5
stz ControlPort+6 ; P2-P3 : 0, police Hercules intégrée
stz ControlPort+7
lda #2
ldx #21 ; fonction 21 : Set Console Font
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
cadre: .byte $00, $FC, $84, $84, $84, $84, $FC, $00
m1: .text "Police remplacee", 13, 0
m2: .text "Police d'origine", 13, 0Police remplacee
Police d'origine2,22 Get Media Key Trinity
Donne la dernière touche multimédia du clavier USB (volume, lecture, piste suivante…) et les touches système, puis les efface.
Entrées : aucune.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | uint16 | code « Consumer Control » (page HID $0C) : $00E9 volume +, $00EA volume −, $00E2 muet, $00CD lecture/pause, $00B5 suivant, $00B6 précédent, $0223 accueil… ; 0 : rien |
P2 | uint8 | touches système : bit 0 veille, bit 1 marche, bit 2 réveil |
Les deux valeurs sont remises à zéro par l'appel : un programme l'interroge régulièrement. Les claviers exposent ces touches sur une seconde interface HID, que le firmware reprend au gestionnaire de manettes.
Texte de la documentation du firmware (anglais)
Returns the last media key pressed on the USB keyboard in Parameters:0,1 (Consumer Control usage, HID usage page $0C : $00E9 volume up, $00EA volume down, $00E2 mute, $00CD play/pause, $00B5 next, $00B6 previous, $0223 home...) and the system keys in Parameter:2 (bit 0 sleep, bit 1 power, bit 2 wake). Both are cleared by this call, so a program polls it ; 0 means nothing pressed since the last call. Keyboards expose these keys on a second HID interface without boot protocol, which the firmware claims from the gamepad manager (Trinity T-39).
C (llvm-mos)
/* Dernière touche multimédia (groupe 2, fonction 22). */
#include <stdio.h>
#include <neo6502.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)
;
}
int main(void) {
libre();
api(2, 22); /* Get Media Key */
uint16_t touche = ControlPort.params[0] | (ControlPort.params[1] << 8);
uint8_t systeme = ControlPort.params[2];
printf("Touche multimedia : %u, systeme : %u\n", touche, systeme); /* 0 : rien */
return 0;
}Touche multimedia : 0, systeme : 0Mad Pascal
// Dernière touche multimédia (groupe 2, fonction 22).
program media;
uses crt, neo6502;
var touche: word;
systeme: byte;
begin
NeoSendMessage(2, 22); // Get Media Key
NeoWaitMessage;
touche := wordParams[0];
systeme := NeoMessage.params[2];
writeln('Touche multimedia : ', touche, ', systeme : ', systeme); // 0 : rien
end.Touche multimedia : 0, systeme : 0NeoBASIC
10 ' Derniere touche multimedia (groupe 2, fonction 22)
20 ' lire les resultats dans des variables juste apres l'appel, avant tout calcul : print et * reutilisent la boite aux lettres
30 while peek($ff00) : wend
40 poke $ff01, 22 : poke $ff00, 2
50 while peek($ff00) : wend : t0 = peek($ff04) : t1 = peek($ff05) : s = peek($ff06) : t = t0 + 256 * t1
60 print "Touche multimedia : ";t;", systeme : ";sTouche multimedia : 0, systeme : 0Assembleur 65C02 (64tass)
; Dernière touche multimédia (groupe 2, fonction 22) : affiche l'octet de poids faible.
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #2
ldx #22 ; fonction 22 : Get Media Key
jsr appel
lda ControlPort+4 ; P0 : code (poids faible)
sta touche
lda ControlPort+6 ; P2 : touches système
sta systeme
lda #<m1
ldx #>m1
jsr ecrire
lda touche
jsr decimal
lda #<m2
ldx #>m2
jsr ecrire
lda systeme
jsr decimal
lda #13
jmp WriteCharacter
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
touche: .byte 0
systeme: .byte 0
m1: .text "Touche multimedia : ", 0
m2: .text ", systeme : ", 0Touche multimedia : 0, systeme : 02,23 Get Lock Keys Trinity
Donne l'état des touches de verrouillage du clavier USB : Verr. Num, Verr. Maj, Arrêt défil.
Entrées : aucune.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | bit 0 Verr. Num, bit 1 Verr. Maj, bit 2 Arrêt défil |
Le firmware bascule ces états à chaque appui et allume les voyants du clavier. Verr. Maj inverse la casse des lettres seulement ; Verr. Num donne les chiffres au pavé numérique ; Arrêt défil n'est qu'un état, libre pour le programme. Verr. Num est éteint au démarrage.
Texte de la documentation du firmware (anglais)
Returns in Parameter:0 the state of the lock keys of the USB keyboard : bit 0 Num Lock, bit 1 Caps Lock, bit 2 Scroll Lock (Trinity T-40). The firmware toggles them on each press and lights the matching LEDs on the keyboard, which the upstream never did. They also drive how keys are read (Trinity T-41) : Caps Lock swaps the case of the letters only, Num Lock gives the numeric keypad its figures (off : the navigation keys printed on the keys). Scroll Lock is only a state and a LED, for the program to use as it likes. Num Lock starts off.
C (llvm-mos)
/* État des touches de verrouillage (groupe 2, fonction 23). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static const char *oui_non(uint8_t b) { return b ? "oui" : "non"; }
int main(void) {
libre();
api(2, 23); /* Get Lock Keys */
uint8_t v = ControlPort.params[0];
printf("Verr. Num : %s, Verr. Maj : %s, Arret defil : %s\n",
oui_non(v & 1), oui_non(v & 2), oui_non(v & 4));
return 0;
}Verr. Num : non, Verr. Maj : non, Arret defil : nonMad Pascal
// État des touches de verrouillage (groupe 2, fonction 23).
program verrous;
uses crt, neo6502;
var v: byte;
function oui_non(b: byte): string;
begin
if b <> 0 then result := 'oui' else result := 'non';
end;
begin
NeoSendMessage(2, 23); // Get Lock Keys
NeoWaitMessage;
v := NeoMessage.params[0];
writeln('Verr. Num : ', oui_non(v and 1), ', Verr. Maj : ', oui_non(v and 2),
', Arret defil : ', oui_non(v and 4));
end.Verr. Num : non, Verr. Maj : non, Arret defil : nonNeoBASIC
10 ' Etat des touches de verrouillage (groupe 2, fonction 23)
20 ' lire les resultats dans des variables juste apres l'appel : print reutilise la boite aux lettres
30 while peek($ff00) : wend
40 poke $ff01, 23 : poke $ff00, 2
50 while peek($ff00) : wend : v = peek($ff04)
60 n$ = "non" : m$ = "non" : d$ = "non"
70 if v & 1 then n$ = "oui"
80 if v & 2 then m$ = "oui"
90 if v & 4 then d$ = "oui"
100 print "Verr. Num : ";n$;", Verr. Maj : ";m$;", Arret defil : ";d$Verr. Num : non, Verr. Maj : non, Arret defil : nonAssembleur 65C02 (64tass)
; État des touches de verrouillage (groupe 2, fonction 23).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #2
ldx #23 ; fonction 23 : Get Lock Keys
jsr appel
lda ControlPort+4 ; bit 0 Num, bit 1 Maj, bit 2 Défil
sta etat
lda #<m1
ldx #>m1
jsr ecrire
lda #1
jsr oui_non
lda #<m2
ldx #>m2
jsr ecrire
lda #2
jsr oui_non
lda #<m3
ldx #>m3
jsr ecrire
lda #4
jsr oui_non
lda #13
jmp WriteCharacter
oui_non:
and etat
beq _non
lda #<oui
ldx #>oui
jmp ecrire
_non: lda #<non
ldx #>non
jmp ecrire
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
etat: .byte 0
m1: .text "Verr. Num : ", 0
m2: .text ", Verr. Maj : ", 0
m3: .text ", Arret defil : ", 0
oui: .text "oui", 0
non: .text "non", 0Verr. Num : non, Verr. Maj : non, Arret defil : non