Group 7 — Controller Official
7,1 Read Default Controller · 7,2 Read Controller Count · 7,3 Read Controller
A controller reads as one byte, one bit per button, from high to low: Y, X, B, A, down, up, right, left (left = bit 0, A = bit 4). Controller 0 is the keyboard (WASD and OPKL, or the arrow keys and ZXCV); plugged USB controllers follow, from 1.
The examples translate the byte into button names. On the bench, the emulator simulates a USB controller with "up" and "A" pressed ($14); on the board, press them yourself.
7,1 Read Default Controller Official
Reads the default controller: the keyboard and all USB controllers combined.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | buttons: Y X B A down up right left, from bit 7 to bit 0 |
The firmware ORs the keyboard with the low byte of each USB controller: the same button may come from either. The example waits for a button to be pressed. In NeoBASIC, joypad(dx, dy) makes this call: it returns A, B, X, Y in bits 0 to 3 and puts -1, 0 or 1 in dx and dy.
NeoBASIC keywords that make this call: joypad()
Firmware documentation text
This reads the status of the base controller into Parameter:0, and is a compatibility API call.
The base controller is the keyboard keys (these are WASD+OPKL or Arrow Keys+ZXCV) or the gamepad controller buttons. Either works.
The 8 bits of the returned byte are the following buttons, most significant first :
Y X B A Down Up Right Left
C (llvm-mos)
/* Attendre un bouton de la manette par défaut (groupe 7, fonction 1). */
#include <stdio.h>
#include <neo/api.h>
static const char *const noms[8] = { "Gauche", "Droite", "Haut", "Bas", "A", "B", "X", "Y" };
static void boutons(uint8_t v) { /* un nom par bit à 1 */
if (v == 0)
printf(" aucun");
for (uint8_t i = 0; i < 8; i++)
if (v & (1 << i))
printf(" %s", noms[i]);
printf("\n");
}
int main(void) {
uint8_t v;
printf("Appuyez sur un bouton\n");
while ((v = neo_controller_read_default()) == 0) /* Read Default Controller */
;
printf("Boutons :");
boutons(v);
return 0;
}Appuyez sur un bouton
Boutons : Haut AMad Pascal
// Attendre un bouton de la manette par défaut (groupe 7, fonction 1).
program manette;
uses crt, neo6502;
var v: byte;
noms: array[0..7] of string[6] = ('Gauche', 'Droite', 'Haut', 'Bas', 'A', 'B', 'X', 'Y');
procedure boutons(v: byte); // un nom par bit à 1
var i: byte;
begin
if v = 0 then write(' aucun');
for i := 0 to 7 do
if v and (1 shl i) <> 0 then write(' ', noms[i]);
writeln;
end;
begin
writeln('Appuyez sur un bouton');
repeat
v := NeoGetJoy; // Read Default Controller
until v <> 0;
write('Boutons :');
boutons(v);
end.Appuyez sur un bouton
Boutons : Haut ANeoBASIC
10 ' Attendre un bouton de la manette par defaut (groupe 7, fonction 1)
20 print "Appuyez sur un bouton"
30 repeat : bx = joypad(dx, dy) : until bx <> 0 | dx <> 0 | dy <> 0
40 gosub 1000
50 print "Boutons :";s$
60 end
1000 ' noms des boutons appuyes, d'apres joypad() : bx boutons, dx et dy directions
1010 s$ = ""
1020 if dx = -1 then s$ = s$ + " Gauche"
1030 if dx = 1 then s$ = s$ + " Droite"
1040 if dy = -1 then s$ = s$ + " Haut"
1050 if dy = 1 then s$ = s$ + " Bas"
1060 if bx & 1 then s$ = s$ + " A"
1070 if bx & 2 then s$ = s$ + " B"
1080 if bx & 4 then s$ = s$ + " X"
1090 if bx & 8 then s$ = s$ + " Y"
1100 if s$ = "" then s$ = " aucun"
1110 returnAppuyez sur un bouton
Boutons : Haut A65C02 assembly (64tass)
; Attendre un bouton de la manette par défaut (groupe 7, 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 #<m
ldx #>m
jsr ecrire
_att: jsr WaitMessage
lda #7
ldx #1 ; fonction 1 : Read Default Controller
jsr appel
lda ControlPort+4 ; P0 : boutons
beq _att
pha
lda #<m2
ldx #>m2
jsr ecrire
pla
jmp boutons
; Affiche le nom de chaque bouton appuyé dans A (un bit par bouton), puis retour à la ligne.
boutons:
sta etat
bne _b
lda #<aucun
ldx #>aucun
jsr ecrire
_b: ldy #0
_bit: lsr etat
bcc _suiv
phy
lda #' '
jsr WriteCharacter
tya
asl a
tax
lda noms,x
pha
lda noms+1,x
tax
pla
jsr ecrire
ply
_suiv: iny
cpy #8
bne _bit
lda #13
jmp WriteCharacter
etat: .byte 0
aucun: .text " aucun", 0
noms: .word n0, n1, n2, n3, n4, n5, n6, n7
n0: .text "Gauche", 0
n1: .text "Droite", 0
n2: .text "Haut", 0
n3: .text "Bas", 0
n4: .text "A", 0
n5: .text "B", 0
n6: .text "X", 0
n7: .text "Y", 0
; 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
m: .text "Appuyez sur un bouton", 13, 0
m2: .text "Boutons :", 0Appuyez sur un bouton
Boutons : Haut A7,2 Read Controller Count Official
Gives the number of plugged USB controllers (the keyboard is not counted).
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | number of USB controllers |
The controllers are then read with 7,3, numbers 1 to this count. On the bench, the emulator simulates one. In NeoBASIC, joycount() makes this call.
NeoBASIC keywords that make this call: joypad(), joycount()
Firmware documentation text
This returns the number of game controllers plugged in to the USB System into Parameter:0. This does not include the keyboard based controller, only physical controller hardware.
C (llvm-mos)
/* Compter les manettes USB (groupe 7, fonction 2). */
#include <stdio.h>
#include <neo/api.h>
int main(void) {
printf("Manettes USB : %u\n", neo_controller_count()); /* Read Controller Count */
return 0;
}Manettes USB : 1Mad Pascal
// Compter les manettes USB (groupe 7, fonction 2).
program compte;
uses crt, neo6502;
var n: byte;
begin
n := NeoGetJoyCount; // Read Controller Count
writeln('Manettes USB : ', n);
end.Manettes USB : 1NeoBASIC
10 ' Compter les manettes USB (groupe 7, fonction 2)
20 print "Manettes USB : ";joycount()Manettes USB : 165C02 assembly (64tass)
; Compter les manettes USB (groupe 7, 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: jsr WaitMessage
lda #7
ldx #2 ; fonction 2 : Read Controller Count
jsr appel
lda ControlPort+4 ; P0 : nombre
pha
lda #<m
ldx #>m
jsr ecrire
pla
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
m: .text "Manettes USB : ", 0Manettes USB : 17,3 Read Controller Official
Reads a given controller: 0 the keyboard, 1 and up the USB controllers.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | controller number |
| Bytes | Type | Meaning |
|---|---|---|
P0-P3 | uint32 | buttons, low byte as in 7,1; the rest is reserved for later |
erreur | uint8 | 1 if the number is above the controller count (7,2) |
Unlike 7,1, the keyboard and each controller are told apart. In NeoBASIC, joypad(n, dx, dy) makes this call, after checking n with 7,2 (range error otherwise).
NeoBASIC keywords that make this call: joypad()
Firmware documentation text
This returns a specific controller status. Controller 0 is the keyboard controller, Controllers 1 upwards are those physical USB devices.
This returns a 32 bit value in Parameters:0..3 which currently is compatible with function 1, but allows for expansion.
The 8 bits of the returned byte are the following buttons, most significant first :
Y X B A Down Up Right Left
C (llvm-mos)
/* Lire le clavier et la manette 1 séparément (groupe 7, fonction 3). */
#include <stdio.h>
#include <neo/api.h>
static const char *const noms[8] = { "Gauche", "Droite", "Haut", "Bas", "A", "B", "X", "Y" };
static void boutons(uint8_t v) { /* un nom par bit à 1 */
if (v == 0)
printf(" aucun");
for (uint8_t i = 0; i < 8; i++)
if (v & (1 << i))
printf(" %s", noms[i]);
printf("\n");
}
int main(void) {
uint8_t clavier = neo_controller_read(0); /* Read Controller : 0 le clavier */
uint8_t m1;
while ((m1 = neo_controller_read(1)) == 0) /* 1 : première manette USB (octet bas) */
;
printf("Clavier :");
boutons(clavier);
printf("Manette 1 :");
boutons(m1);
return 0;
}Clavier : aucun
Manette 1 : Haut AMad Pascal
// Lire le clavier et la manette 1 séparément (groupe 7, fonction 3).
program deux;
uses crt, neo6502;
var clavier, m1: byte;
noms: array[0..7] of string[6] = ('Gauche', 'Droite', 'Haut', 'Bas', 'A', 'B', 'X', 'Y');
procedure boutons(v: byte); // un nom par bit à 1
var i: byte;
begin
if v = 0 then write(' aucun');
for i := 0 to 7 do
if v and (1 shl i) <> 0 then write(' ', noms[i]);
writeln;
end;
begin
clavier := NeoGetJoy(0); // Read Controller : 0 le clavier
repeat
m1 := NeoGetJoy(1); // 1 : première manette USB
until m1 <> 0;
write('Clavier :');
boutons(clavier);
write('Manette 1 :');
boutons(m1);
end.Clavier : aucun
Manette 1 : Haut ANeoBASIC
10 ' Lire le clavier et la manette 1 separement (groupe 7, fonction 3)
20 bx = joypad(0, dx, dy) : gosub 1000 : c$ = s$
30 repeat : bx = joypad(1, dx, dy) : until bx <> 0 | dx <> 0 | dy <> 0
40 gosub 1000
50 print "Clavier :";c$
60 print "Manette 1 :";s$
70 end
1000 ' noms des boutons appuyes, d'apres joypad() : bx boutons, dx et dy directions
1010 s$ = ""
1020 if dx = -1 then s$ = s$ + " Gauche"
1030 if dx = 1 then s$ = s$ + " Droite"
1040 if dy = -1 then s$ = s$ + " Haut"
1050 if dy = 1 then s$ = s$ + " Bas"
1060 if bx & 1 then s$ = s$ + " A"
1070 if bx & 2 then s$ = s$ + " B"
1080 if bx & 4 then s$ = s$ + " X"
1090 if bx & 8 then s$ = s$ + " Y"
1100 if s$ = "" then s$ = " aucun"
1110 returnClavier : aucun
Manette 1 : Haut A65C02 assembly (64tass)
; Lire le clavier et la manette 1 séparément (groupe 7, 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 #0 ; 0 : le clavier
jsr lire
sta clavier
_att: lda #1 ; 1 : première manette USB
jsr lire
beq _att
sta m1
lda #<t0
ldx #>t0
jsr ecrire
lda clavier
jsr boutons
lda #<t1
ldx #>t1
jsr ecrire
lda m1
jmp boutons
; Boutons de la manette A (7,3), rendus dans A.
lire: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0 : numéro de manette
lda #7
ldx #3 ; fonction 3 : Read Controller
jsr appel
lda ControlPort+4
rts
; Affiche le nom de chaque bouton appuyé dans A (un bit par bouton), puis retour à la ligne.
boutons:
sta etat
bne _b
lda #<aucun
ldx #>aucun
jsr ecrire
_b: ldy #0
_bit: lsr etat
bcc _suiv
phy
lda #' '
jsr WriteCharacter
tya
asl a
tax
lda noms,x
pha
lda noms+1,x
tax
pla
jsr ecrire
ply
_suiv: iny
cpy #8
bne _bit
lda #13
jmp WriteCharacter
etat: .byte 0
aucun: .text " aucun", 0
noms: .word n0, n1, n2, n3, n4, n5, n6, n7
n0: .text "Gauche", 0
n1: .text "Droite", 0
n2: .text "Haut", 0
n3: .text "Bas", 0
n4: .text "A", 0
n5: .text "B", 0
n6: .text "X", 0
n7: .text "Y", 0
; 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
clavier: .byte 0
m1: .byte 0
t0: .text "Clavier :", 0
t1: .text "Manette 1 :", 0Clavier : aucun
Manette 1 : Haut A