Tachibana
Language: English

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.

Outputs
BytesTypeMeaning
P0uint8buttons: 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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Appuyez sur un bouton
Boutons : Haut A
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Appuyez sur un bouton
Boutons : Haut A
NeoBASIC
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 return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Appuyez sur un bouton
Boutons : Haut A
65C02 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 :", 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Appuyez sur un bouton
Boutons : Haut A

7,2 Read Controller Count Official

Gives the number of plugged USB controllers (the keyboard is not counted).

Inputs: none.

Outputs
BytesTypeMeaning
P0uint8number 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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Manettes USB : 1
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Manettes USB : 1
NeoBASIC
10 ' Compter les manettes USB (groupe 7, fonction 2)
20 print "Manettes USB : ";joycount()
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Manettes USB : 1
65C02 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 : ", 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Manettes USB : 1

7,3 Read Controller Official

Reads a given controller: 0 the keyboard, 1 and up the USB controllers.

Inputs
BytesTypeMeaning
P0uint8controller number
Outputs
BytesTypeMeaning
P0-P3uint32buttons, low byte as in 7,1; the rest is reserved for later
erreuruint81 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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Clavier : aucun
Manette 1 : Haut A
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Clavier : aucun
Manette 1 : Haut A
NeoBASIC
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 return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Clavier : aucun
Manette 1 : Haut A
65C02 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 :", 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Clavier : aucun
Manette 1 : Haut A

← The Neo6502 API