Group 2 — Console Official
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 Official
Writes a character at the cursor position. Duplicate of function 2,6, kept for backward compatibility.
| Bytes | Type | Meaning |
|---|---|---|
P0 | char | the character (or a control code, see 2,6) |
Outputs: none.
Prefer function 2,6, which does the same.
Firmware documentation text
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) : wendBonjour65C02 assembly (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 Official
Removes the oldest key press from the keyboard queue and gives its ASCII code; 0 if the queue is empty.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0 | char | ASCII code of the key, 0 if none |
Meant for text input. For a game, read the key state (1,2 or 7,1): the queue does not tell whether a key is still held. In NeoBASIC, inkey$() makes the same call.
NeoBASIC keywords that make this call: inkey$()
Firmware documentation text
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 : A65C02 assembly (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 Official
Tells whether the keyboard queue is empty, without removing anything from it.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | $FF if the queue is empty, 0 if a key is waiting |
Mind the sense: $FF means "nothing to read".
Firmware documentation text
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
A65C02 assembly (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 Official
Reads back the text of the screen line where the cursor is (a logical line, possibly spanning several screen lines), then moves the cursor to the start of the next line.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of a 256-byte buffer that receives the line (length, then text) |
| Bytes | Type | Meaning |
|---|---|---|
tampon | string | the line, without trailing spaces |
Nothing is awaited from the keyboard: the function reads what is already displayed. This is how a full-screen editor gets the line on which Enter was pressed. For real input, the kernel offers ReadLine ($FFEB).
Firmware documentation text
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 monde65C02 assembly (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 Official
Assigns a text to a function key F1 to F10: pressing the key types it as if from the keyboard.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | key number, 1 (F1) to 10 (F10) |
P2-P3 | addr | address of the text, length-prefixed |
Outputs: none.
F11 and F12 cannot be defined. The text address is at P2-P3 (P1 is not used). In NeoBASIC, fkey n, "text" makes the same call. In Mad Pascal 1.7.8, NeoDefineHotkey stores the address at P0-P1, overwriting the key number: the call fails (error 1); the example makes the call directly.
NeoBASIC keywords that make this call: fkey
Firmware documentation text
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"65C02 assembly (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 Official
Redraws one of the characters 192 to 255 of the font, row by row (6 columns × 7 rows).
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | character code (192 to 255) |
P1-P7 | 7 × uint8 | the 7 rows of the bitmap, top to bottom; bits 0 to 5 = columns |
Outputs: none.
Redefined characters stay until reset. In NeoBASIC, defchr c, r1, …, r7 makes the same call.
NeoBASIC keywords that make this call: defchr
Firmware documentation text
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 : .65C02 assembly (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 Official
Writes a character, or performs a control code, at the cursor position.
| Bytes | Type | Meaning |
|---|---|---|
P0 | char | 32-126 and $A0-$FF: displayed character; $80-$8F: text colour; $90-$9F: background colour; control codes: 8 backspace, 9 tab, 10 line feed, 12 clear screen, 13 carriage return, 20 home, 1/4/19/23 cursor left/right/down/up, 24 invert the character under the cursor, 26 delete |
Outputs: none.
This is the kernel routine WriteCharacter ($FFF1); the codes come from CONWrite in the firmware.
Firmware documentation text
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) : wendBonjour65C02 assembly (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 Official
Moves the cursor to a screen cell (column, row).
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | column (0 = left) |
P1 | uint8 | row (0 = top) |
Outputs: none.
In NeoBASIC, cursor x, y makes the same call. The screen size is given by 2,9.
NeoBASIC keywords that make this call: cursor
Firmware documentation text
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" Ici65C02 assembly (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 Official
Displays the texts assigned to the function keys (see 2,4).
Inputs: none.
Outputs: none.
In NeoBASIC, fkey without arguments makes the same call.
NeoBASIC keywords that make this call: fkey
Firmware documentation text
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"65C02 assembly (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 Official
Gives the console size in characters.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | height (number of rows) |
P1 | uint8 | width (number of columns) |
Mind the order: the height comes first. The size depends on the video mode (5,9).
Firmware documentation text
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 lignes65C02 assembly (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 Official
Inserts a blank line at the given row; the following rows move down, the last row of the screen is lost.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | row number (0 = top) |
Outputs: none.
A console support function (the editor uses it); the firmware documentation advises against using it directly.
Firmware documentation text
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 C65C02 assembly (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 Official
Deletes the given row; the following rows move up, a blank row appears at the bottom of the screen.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | row number (0 = top) |
Outputs: none.
A console support function (the editor uses it); the firmware documentation advises against using it directly.
Firmware documentation text
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 C65C02 assembly (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 Official
Clears the console screen and puts the cursor back at the top left.
Inputs: none.
Outputs: none.
Control code 12 sent through 2,6 has the same effect. Cursor visibility (2,19) is restored.
Firmware documentation text
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 efface65C02 assembly (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 Official
Gives the cursor position (column, row).
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | column |
P1 | uint8 | row |
NeoBASIC keywords that make this call: print
Firmware documentation text
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 2965C02 assembly (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 Official
Clears a rectangle of the screen, bounds included.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | start column |
P1 | uint8 | start row |
P2 | uint8 | end column (included) |
P3 | uint8 | end row (included) |
Outputs: none.
Bounds are clipped to the screen; the rectangle is filled with spaces in the current colours.
Firmware documentation text
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 XXXX65C02 assembly (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 Official
Selects the text and background colours for the characters written afterwards.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | text colour (0 to 15) |
P1 | uint8 | background colour (0 to 15) |
Outputs: none.
Codes $80-$8F and $90-$9F written through 2,6 do the same, character by character. 2,18 reads the current colours back, to restore them.
Firmware documentation text
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 couleur65C02 assembly (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 Official
Swaps the colours (text and background) of the cursor cell; a second call restores them.
Inputs: none.
Outputs: none.
A support function (cursor blinking); the firmware documentation advises against using it.
Firmware documentation text
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 fois65C02 assembly (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 Official
Writes spaces until the cursor reaches the given column (used by NeoBASIC tab()).
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | column to reach |
Outputs: none.
If the cursor is already beyond, nothing is written. In NeoBASIC, tab(n) inside a print makes the same call.
NeoBASIC keywords that make this call: tab()
Firmware documentation text
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 B65C02 assembly (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 Official
Gives the current text (ink) and background (paper) colours.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | text colour |
P1 | uint8 | background colour |
Firmware documentation text
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 : 065C02 assembly (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 Official
Shows or hides the blinking cursor.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | non zero: visible, 0: hidden |
Outputs: none.
Clearing the screen (2,12) makes the cursor visible again.
Firmware documentation text
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 reaffiche65C02 assembly (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
Copies everything written to the console to the debug port (the GP28/GP29 UART on the board): a PC can thus capture the screen text.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | 0: off; 1: printable characters and Enter (as CR LF); 2: also characters $A0-$FF |
Outputs: none.
In the emulators, the echo goes to stderr.
Firmware documentation text
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 debogage65C02 assembly (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
Replaces the console font for characters $20-$7F with a font in RAM; address 0 restores the built-in font.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | 96 glyphs of 8 bytes (one byte per row, bit 7 = leftmost pixel), $20 to $7F; 0: built-in font |
P2-P3 | addr | 96 glyphs of 14 bytes for the 9×14 cells of Hercules mode (1); 0: keep the built-in 8×14 font |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | non zero if the glyphs would run past the end of memory |
The font is read in place at every repaint, with no copy: keep it intact while it is selected. The whole console is repainted. A mode change (5,9) or a reset restores the built-in font. Characters $A0-$BF (Latin-1 symbols) and $C0-$FF (2,5) are unchanged.
Firmware documentation text
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'origine65C02 assembly (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
Gives the last multimedia key of the USB keyboard (volume, play, next track…) and the system keys, then clears them.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | uint16 | Consumer Control usage (HID page $0C): $00E9 volume up, $00EA volume down, $00E2 mute, $00CD play/pause, $00B5 next, $00B6 previous, $0223 home…; 0: nothing |
P2 | uint8 | system keys: bit 0 sleep, bit 1 power, bit 2 wake |
Both values are cleared by the call: a program polls it. Keyboards expose these keys on a second HID interface, which the firmware claims from the gamepad manager.
Firmware documentation text
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 : 065C02 assembly (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
Gives the state of the USB keyboard lock keys: Num Lock, Caps Lock, Scroll Lock.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | bit 0 Num Lock, bit 1 Caps Lock, bit 2 Scroll Lock |
The firmware toggles these states on each press and lights the keyboard LEDs. Caps Lock swaps the case of letters only; Num Lock gives the keypad its figures; Scroll Lock is only a state, free for the program. Num Lock starts off.
Firmware documentation text
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 : non65C02 assembly (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