Tachibana
Langue : français

Groupe 3 — Fichiers Officiel

3,1 List Directory · 3,2 Load File · 3,3 Store File · 3,4 File Open · 3,5 File Close · 3,6 File Seek · 3,7 File Tell · 3,8 File Read · 3,9 File Write · 3,10 File Size · 3,11 File Set Size · 3,12 File Rename · 3,13 File Delete · 3,14 Create Directory · 3,15 Change Directory · 3,16 File Stat · 3,17 Open Directory · 3,18 Read Directory · 3,19 Close Directory · 3,20 Copy File · 3,21 Set file attributes · 3,22 Check End of File. · 3,23 Get Current Working Directory. · 3,24 Volume Info · 3,25 Select Volume · 3,26 Get Current Volume · 3,27 File Read Paged · 3,28 File Read Background · 3,29 Last Entry Date Time · 3,32 List Filtered

3,1 List Directory Officiel

Affiche la liste des fichiers du répertoire courant.

Entrées : aucune.

Sorties : aucune.

En NeoBASIC, cat fait le même appel ; cat "texte" filtre (3,32).

Texte de la documentation du firmware (anglais)

Display the file listing of the present directory.

C (llvm-mos)
/* Lister le répertoire courant (groupe 3, fonction 1). */
#include <neo/api.h>

int main(void) {
    neo_file_list_directory();
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
PROG.NEO                        43 bytes.
Mad Pascal
// Lister le répertoire courant (groupe 3, fonction 1).
program liste;
uses crt, neo6502;
begin
  NeoShowDir;                                   // List Directory
  NeoWaitMessage;
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
PROG.NEO                        132 bytes.
NeoBASIC
10 ' Lister le repertoire courant (groupe 3, fonction 1)
20 cat
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
prog.bas                        321 bytes.
boot                            <Dir>
Assembleur 65C02 (64tass)
; Lister le répertoire courant (groupe 3, 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:  jsr WaitMessage
        lda #3
        ldx #1                     ; fonction 1 : List Directory
        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
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
PROG.NEO                        106 bytes.

3,2 Load File Officiel

Charge tout un fichier en mémoire, à l'adresse donnée ; l'adresse $FFFF le charge dans la mémoire graphique (sprites, tuiles, images).

Entrées
OctetsTypeRôle
P0-P1addradresse du nom de fichier (précédé de sa longueur)
P2-P3addradresse de destination, ou $FFFF pour la mémoire graphique
Sorties
OctetsTypeRôle
erreuruint80 si le fichier a été chargé (sinon code d'erreur, ex. $11 fichier absent)

L'exemple crée d'abord le fichier avec 3,3. Rien ne borne la taille : le fichier doit tenir à l'adresse choisie.

Texte de la documentation du firmware (anglais)

Load a file by name into memory. On input:

Parameters:0,1 points to the length-prefixed filename string; Parameters:2,3 contains the location to write the data to. If the address is $FFFF, the file will instead be loaded into the graphics working memory, used for sprites, tiles, images.

On output: Error location contains an error/status code.

C (llvm-mos)
/* Enregistrer un texte, puis le recharger (groupe 3, fonctions 3 et 2). */
#include <stdio.h>
#include <string.h>
#include <neo/api.h>

static char texte[16] = "Bonjour";
static char relu[16];

int main(void) {
    neo_file_store("salut.txt", texte, strlen(texte) + 1);   /* 3,3 : avec le zéro final */
    neo_file_load("salut.txt", relu);                      /* Load File */
    if (neo_api_error())
        printf("Erreur %u\n", neo_api_error());
    else
        printf("Charge : %s\n", relu);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Charge : Bonjour
Mad Pascal
// Enregistrer un texte, puis le recharger (groupe 3, fonctions 3 et 2).
program charger;
uses crt, neo6502;
var texte, relu: string[16];
    e: byte;
begin
  texte := 'Bonjour';
  NeoSave('salut.txt', word(@texte), length(texte) + 1);   // 3,3 : la chaîne Pascal entière
  if NeoLoad('salut.txt', word(@relu)) then             // Load File
    writeln('Charge : ', relu)
  else
  begin
    e := NeoMessage.error;                      // à lire avant writeln, qui passe par l'API
    writeln('Erreur ', e);
  end;
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Charge : Bonjour
NeoBASIC
10 ' Enregistrer un texte, puis le recharger (groupe 3, fonctions 3 et 2)
20 t = alloc(16) : n$ = "Bonjour" : a = t : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 save "salut.txt", t, 8
40 r = alloc(16) : n$ = "salut.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
50 while peek($ff00) : wend
60 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff06, r & 255 : poke $ff07, r >> 8 : poke $ff01, 2 : poke $ff00, 3
70 while peek($ff00) : wend : e = peek($ff02)
80 s$ = "" : for i = 1 to peek(r) : s$ = s$ + chr$(peek(r + i)) : next i
90 if e = 0 then print "Charge : ";s$
100 if e <> 0 then print "Erreur ";e
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Charge : Bonjour
Assembleur 65C02 (64tass)
; Enregistrer un texte, puis le recharger (groupe 3, fonctions 3 et 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            ; 3,3 : créer le fichier
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<texte
        sta ControlPort+6
        lda #>texte
        sta ControlPort+7
        lda #8                     ; 7 lettres + zéro final
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        jsr WaitMessage
        lda #<nom
        sta ControlPort+4          ; P0-P1 : nom
        lda #>nom
        sta ControlPort+5
        lda #<relu
        sta ControlPort+6          ; P2-P3 : destination
        lda #>relu
        sta ControlPort+7
        lda #3
        ldx #2                     ; fonction 2 : Load File
        jsr appel
        lda #<m
        ldx #>m
        jsr ecrire
        lda #<relu
        ldx #>relu
        jsr ecrire
        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

nom:    .byte 9
        .text "salut.txt"
texte:  .text "Bonjour", 0
relu:   .fill 16
m:      .text "Charge : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Charge : Bonjour

3,3 Store File Officiel

Enregistre une zone de mémoire dans un fichier (créé ou remplacé).

Entrées
OctetsTypeRôle
P0-P1addradresse du nom de fichier (précédé de sa longueur)
P2-P3addradresse des données
P4-P5uint16nombre d'octets
Sorties
OctetsTypeRôle
erreuruint80 si le fichier a été écrit

En NeoBASIC, save "nom", adresse, longueur fait le même appel (save "nom" seul enregistre le programme). En C, neo_file_stat de llvm-mos (compilateur c798c31) rend une taille fausse (0) alors que le firmware renvoie la bonne en P0-P3 : l'exemple appelle 3,16 directement.

Texte de la documentation du firmware (anglais)

Saves data in memory to a file. On input:

Parameters:0,1 points to the length-prefixed filename string; Parameters:2,3 contains the location to read data from; Parameters:4,5 specified the number of bytes to store.

On output: Error location contains an error/status code.

C (llvm-mos)
/* Enregistrer 7 octets, puis vérifier la taille du fichier (groupe 3, fonctions 3 et 16). */
/* neo_file_stat (llvm-mos, compilateur c798c31) rend une taille fausse : 3,16 est appelé directement. */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
    ControlPort.function = fonction;
    ControlPort.command = groupe;
    while (ControlPort.command)        /* attendre la fin */
        ;
}
static void libre(void) {              /* attendre que la boîte aux lettres soit libre */
    while (ControlPort.command)
        ;
}

static const uint8_t nom[] = "\x09" "salut.txt";      /* longueur, puis le nom */

int main(void) {
    neo_file_store("salut.txt", "Bonjour", 7);  /* Store File */
    libre();
    ControlPort.params[0] = (uint16_t)nom & 0xFF;
    ControlPort.params[1] = (uint16_t)nom >> 8;
    api(3, 16);                                 /* File Stat : taille en P0-P3 */
    uint32_t taille = ControlPort.params[0] | ((uint32_t)ControlPort.params[1] << 8)
                    | ((uint32_t)ControlPort.params[2] << 16) | ((uint32_t)ControlPort.params[3] << 24);
    printf("salut.txt : %lu octets\n", (unsigned long)taille);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
salut.txt : 7 octets
Mad Pascal
// Enregistrer 7 octets, puis vérifier la taille du fichier (groupe 3, fonctions 3 et 16).
program sauver;
uses crt, neo6502;
var texte, nom: string[16];
    taille: cardinal;
    attr: byte;
begin
  texte := 'Bonjour';
  NeoSave('salut.txt', word(@texte) + 1, 7);    // Store File : les 7 lettres
  nom := 'salut.txt';
  if NeoStatFile(@nom, taille, attr) then       // 3,16 : taille
    writeln('salut.txt : ', taille, ' octets');
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
salut.txt : 7 octets
NeoBASIC
10 ' Enregistrer 7 octets, puis verifier la taille du fichier (groupe 3, fonctions 3 et 16)
20 t = alloc(8) : for i = 1 to 7 : poke t + i - 1, asc(mid$("Bonjour", i, 1)) : next i
30 save "salut.txt", t, 7
40 n$ = "salut.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
50 while peek($ff00) : wend
60 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 16 : poke $ff00, 3
70 while peek($ff00) : wend : s = peek($ff04) + 256 * peek($ff05)
80 print "salut.txt : ";s;" octets"
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
salut.txt : 7 octets
Assembleur 65C02 (64tass)
; Enregistrer 7 octets, puis vérifier la taille du fichier (groupe 3, fonctions 3 et 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 #<nom
        sta ControlPort+4          ; P0-P1 : nom
        lda #>nom
        sta ControlPort+5
        lda #<texte
        sta ControlPort+6          ; P2-P3 : données
        lda #>texte
        sta ControlPort+7
        lda #7
        sta ControlPort+8          ; P4-P5 : 7 octets
        stz ControlPort+9
        lda #3
        ldx #3                     ; fonction 3 : Store File
        jsr appel
        jsr WaitMessage
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #3
        ldx #16                    ; 3,16 : File Stat
        jsr appel
        lda ControlPort+4          ; taille (octet de poids faible)
        pha
        lda #<m1
        ldx #>m1
        jsr ecrire
        pla
        jsr decimal
        lda #<m2
        ldx #>m2
        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

nom:    .byte 9
        .text "salut.txt"
texte:  .text "Bonjour"
m1:     .text "salut.txt : ", 0
m2:     .text " octets", 13, 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
salut.txt : 7 octets

3,4 File Open Officiel

Ouvre un fichier sur un canal, en lecture, en écriture, ou les deux.

Entrées
OctetsTypeRôle
P0uint8numéro du canal
P1-P2addradresse du nom (précédé de sa longueur)
P3uint8mode : 0 lecture seule, 1 écriture seule, 2 lecture-écriture, 3 créer (ou vider) puis lecture-écriture
Sorties
OctetsTypeRôle
erreuruint8non nul si l'ouverture a échoué (fichier absent en modes 0 à 2, canal déjà ouvert…)

Ouvrir le même fichier sur deux canaux a un comportement indéfini. En NeoBASIC, open input n, "nom" (mode 0) et open output n, "nom" (mode 3) font le même appel.

Mots-clés NeoBASIC qui font cet appel : open

Texte de la documentation du firmware (anglais)

Opens a file into a specific channel. On input:

Parameter:0 contains the file channel to open; Parameters:1,2 points to the length-prefixed filename string; Parameter:3 contains the open mode. See below.

Valid open modes are: 0 opens the file for read-only access; 1 opens the file for write-only access; 2 opens the file for read-write access; 3 creates the file if it doesn't already exist, truncates it if it does, and opens the file for read-write access.

Modes 0 to 2 will fail if the file does not already exist. If the channel is already open, the call fails. Opening the same file more than once on different channels has undefined behaviour, and is not recommended.

C (llvm-mos)
/* Créer un fichier sur le canal 1, y écrire, le fermer (groupe 3, fonctions 4, 9 et 5). */
#include <stdio.h>
#include <neo/api.h>

int main(void) {
    neo_file_open(1, "canal.txt", NEO_FILE_CREATE);     /* File Open, mode 3 */
    if (neo_api_error()) {
        printf("Ouverture impossible\n");
        return 0;
    }
    uint32_t n = neo_file_write(1, "Bonjour", 7);       /* 3,9 */
    neo_file_close(1);                                   /* 3,5 */
    printf("Ecrit : %lu octets\n", (unsigned long)n);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Ecrit : 7 octets
Mad Pascal
// Créer un fichier sur le canal 1, y écrire, le fermer (groupe 3, fonctions 4, 9 et 5).
program ouvrir;
uses crt, neo6502;
var nom, texte: string[16];
    n: word;
begin
  nom := 'canal.txt';
  texte := 'Bonjour';
  if not NeoOpenFile(1, @nom, 3) then           // File Open, mode 3 : créer
  begin
    writeln('Ouverture impossible');
    exit;
  end;
  n := NeoWriteFile(1, word(@texte) + 1, 7);    // 3,9
  NeoCloseFile(1);                              // 3,5
  writeln('Ecrit : ', n, ' octets');
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Ecrit : 7 octets
NeoBASIC
10 ' Creer un fichier sur le canal 1, y ecrire, le fermer (groupe 3, fonctions 4, 9 et 5)
20 n$ = "canal.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 d = alloc(8) : for i = 1 to 7 : poke d + i - 1, asc(mid$("Bonjour", i, 1)) : next i
40 while peek($ff00) : wend
50 poke $ff04, 1 : poke $ff05, a & 255 : poke $ff06, a >> 8 : poke $ff07, 3 : poke $ff01, 4 : poke $ff00, 3
60 while peek($ff00) : wend : e = peek($ff02)
70 if e then print "Ouverture impossible" : end
80 poke $ff04, 1 : poke $ff05, d & 255 : poke $ff06, d >> 8 : poke $ff07, 7 : poke $ff08, 0 : poke $ff01, 9 : poke $ff00, 3
90 while peek($ff00) : wend : n = peek($ff07) + 256 * peek($ff08)
100 close
110 print "Ecrit : ";n;" octets"
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Ecrit : 7 octets
Assembleur 65C02 (64tass)
; Créer un fichier sur le canal 1, y écrire, le fermer (groupe 3, fonctions 4, 9 et 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 #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<nom
        sta ControlPort+5          ; P1-P2 : nom
        lda #>nom
        sta ControlPort+6
        lda #3
        sta ControlPort+7          ; P3 : mode 3, créer
        lda #3
        ldx #4                     ; fonction 4 : File Open
        jsr appel
        lda ControlPort+2
        bne _err
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; canal 1
        lda #<texte
        sta ControlPort+5          ; P1-P2 : données
        lda #>texte
        sta ControlPort+6
        lda #7
        sta ControlPort+7          ; P3-P4 : 7 octets
        stz ControlPort+8
        lda #3
        ldx #9                     ; 3,9 : File Write
        jsr appel
        lda ControlPort+7          ; octets écrits
        sta ecrits
        jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #3
        ldx #5                     ; 3,5 : File Close
        jsr appel
        lda #<m1
        ldx #>m1
        jsr ecrire
        lda ecrits
        jsr decimal
        lda #<m2
        ldx #>m2
        jmp ecrire
_err:   lda #<err
        ldx #>err
        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

ecrits: .byte 0
nom:    .byte 9
        .text "canal.txt"
texte:  .text "Bonjour"
m1:     .text "Ecrit : ", 0
m2:     .text " octets", 13, 0
err:    .text "Ouverture impossible", 13, 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Ecrit : 7 octets

3,5 File Close Officiel

Ferme un canal ; $FF ferme tous les canaux ouverts.

Entrées
OctetsTypeRôle
P0uint8numéro du canal, ou $FF pour tous

Sorties : aucune.

Fermer un fichier écrit vide ses tampons sur le disque. En NeoBASIC, close fait le même appel.

Mots-clés NeoBASIC qui font cet appel : close

Texte de la documentation du firmware (anglais)

Closes a particular channel. On input:

Parameter:0 contains the file channel to close. If this is $FF this closes all open files.

C (llvm-mos)
/* Ouvrir puis fermer le canal 1 (groupe 3, fonction 5). */
#include <stdio.h>
#include <neo/api.h>

int main(void) {
    neo_file_open(1, "vide.txt", NEO_FILE_CREATE);  /* 3,4 */
    neo_file_close(1);                              /* File Close */
    printf("Canal 1 ferme, erreur %u\n", neo_api_error());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Canal 1 ferme, erreur 0
Mad Pascal
// Ouvrir puis fermer le canal 1 (groupe 3, fonction 5).
program fermer;
uses crt, neo6502;
var nom: string[16];
    e: byte;
begin
  nom := 'vide.txt';
  NeoOpenFile(1, @nom, 3);                      // 3,4
  NeoCloseFile(1);                              // File Close
  e := NeoMessage.error;                        // à lire avant writeln, qui passe par l'API
  writeln('Canal 1 ferme, erreur ', e);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Canal 1 ferme, erreur 0
NeoBASIC
10 ' Ouvrir puis fermer le canal 1 (groupe 3, fonction 5)
20 n$ = "vide.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 m = 3 : while peek($ff00) : wend : poke $ff04, 1 : poke $ff05, a & 255 : poke $ff06, a >> 8 : poke $ff07, m : poke $ff01, 4 : poke $ff00, 3 : while peek($ff00) : wend
40 poke $ff04, 1 : poke $ff01, 5 : poke $ff00, 3
50 while peek($ff00) : wend : e = peek($ff02)
60 print "Canal 1 ferme, erreur ";e
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Canal 1 ferme, erreur 0
Assembleur 65C02 (64tass)
; Ouvrir puis fermer le canal 1 (groupe 3, 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:  lda #3
        jsr ouvrir
        jsr fermer                 ; fonction 5 : File Close
        lda ControlPort+2
        pha
        lda #<m
        ldx #>m
        jsr ecrire
        pla
        jsr decimal
        lda #13
        jmp WriteCharacter
; Ouvrir abc.txt sur le canal 1 dans le mode A.
ouvrir: pha
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<nom
        sta ControlPort+5          ; P1-P2 : nom
        lda #>nom
        sta ControlPort+6
        pla
        sta ControlPort+7          ; P3 : mode
        lda #3
        ldx #4                     ; 3,4 : File Open
        jmp appel

; Fermer le canal 1.
fermer: jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #3
        ldx #5                     ; 3,5 : File Close
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

m:      .text "Canal 1 ferme, erreur ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Canal 1 ferme, erreur 0

3,6 File Seek Officiel

Place la position de lecture et d'écriture d'un canal à l'octet voulu.

Entrées
OctetsTypeRôle
P0uint8numéro du canal
P1-P4uint32position (0 = début du fichier)

Sorties : aucune.

On peut aller au-delà de la fin pour agrandir le fichier ; savoir si la taille change au positionnement ou à l'écriture n'est pas défini.

Texte de la documentation du firmware (anglais)

Seeks the file opened on a particular channel to a location. On input:

Parameter:0 contains the file channel to operate on; Parameters:1..4 contains the file location.

You can seek beyond the end of a file to extend the file. However, whether the file size changes when the seek happens, or when you perform the write is undefined behavior.

C (llvm-mos)
/* Lire l'octet en position 4 de ABCDEFGH (groupe 3, fonction 6). */
#include <stdio.h>
#include <neo/api.h>

int main(void) {
    char c;
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_open(1, "abc.txt", NEO_FILE_READ);
    neo_file_seek(1, 4);                        /* File Seek */
    neo_file_read(1, &c, 1);                    /* 3,8 */
    neo_file_close(1);
    printf("Octet a la position 4 : %c\n", c);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Octet a la position 4 : E
Mad Pascal
// Lire l'octet en position 4 de ABCDEFGH (groupe 3, fonction 6).
program seek;
uses crt, neo6502;
var texte, nom: string[16];
    c: byte;
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := 'abc.txt';
  NeoOpenFile(1, @nom, 0);
  NeoSeekPos(1, 4);                             // File Seek
  NeoReadFile(1, word(@c), 1);                  // 3,8
  NeoCloseFile(1);
  writeln('Octet a la position 4 : ', chr(c));
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Octet a la position 4 : E
NeoBASIC
10 ' Lire l'octet en position 4 de ABCDEFGH (groupe 3, fonction 6)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 b = alloc(4) : m = 0 : while peek($ff00) : wend : poke $ff04, 1 : poke $ff05, a & 255 : poke $ff06, a >> 8 : poke $ff07, m : poke $ff01, 4 : poke $ff00, 3 : while peek($ff00) : wend
40 poke $ff04, 1 : poke $ff05, 4 : poke $ff06, 0 : poke $ff07, 0 : poke $ff08, 0 : poke $ff01, 6 : poke $ff00, 3
50 while peek($ff00) : wend
60 poke $ff04, 1 : poke $ff05, b & 255 : poke $ff06, b >> 8 : poke $ff07, 1 : poke $ff08, 0 : poke $ff01, 8 : poke $ff00, 3
70 while peek($ff00) : wend
80 close
90 print "Octet a la position 4 : ";chr$(peek(b))
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Octet a la position 4 : E
Assembleur 65C02 (64tass)
; Lire l'octet en position 4 de ABCDEFGH (groupe 3, 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:
        jsr WaitMessage            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        lda #0
        jsr ouvrir                 ; lecture seule
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #4
        sta ControlPort+5          ; P1-P4 : position 4
        stz ControlPort+6
        stz ControlPort+7
        stz ControlPort+8
        lda #3
        ldx #6                     ; fonction 6 : File Seek
        jsr appel
        jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #<octet
        sta ControlPort+5          ; P1-P2 : destination
        lda #>octet
        sta ControlPort+6
        lda #1
        sta ControlPort+7          ; P3-P4 : 1 octet
        stz ControlPort+8
        lda #3
        ldx #8                     ; 3,8 : File Read
        jsr appel
        jsr fermer
        lda #<m
        ldx #>m
        jsr ecrire
        lda octet
        jsr WriteCharacter
        lda #13
        jmp WriteCharacter
; Ouvrir abc.txt sur le canal 1 dans le mode A.
ouvrir: pha
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<nom
        sta ControlPort+5          ; P1-P2 : nom
        lda #>nom
        sta ControlPort+6
        pla
        sta ControlPort+7          ; P3 : mode
        lda #3
        ldx #4                     ; 3,4 : File Open
        jmp appel

; Fermer le canal 1.
fermer: jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #3
        ldx #5                     ; 3,5 : File Close
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

octet:  .byte 0
m:      .text "Octet a la position 4 : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Octet a la position 4 : E

3,7 File Tell Officiel

Donne la position de lecture et d'écriture d'un canal.

Entrées
OctetsTypeRôle
P0uint8numéro du canal
Sorties
OctetsTypeRôle
P1-P4uint32position
Texte de la documentation du firmware (anglais)

Returns the current seek location for the file opened on a particular channel. On input:

Parameter:0 contains the file channel to operate on.

On output:

Parameters:1..4 contains the seek location within the file.

C (llvm-mos)
/* Position après avoir lu 3 octets (groupe 3, fonction 7). */
#include <stdio.h>
#include <neo/api.h>

int main(void) {
    char tampon[3];
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_open(1, "abc.txt", NEO_FILE_READ);
    neo_file_read(1, tampon, 3);                /* 3,8 */
    uint32_t pos = neo_file_tell(1);            /* File Tell */
    neo_file_close(1);
    printf("Position apres 3 octets lus : %lu\n", (unsigned long)pos);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Position apres 3 octets lus : 3
Mad Pascal
// Position après avoir lu 3 octets (groupe 3, fonction 7).
program tell;
uses crt, neo6502;
var texte, nom: string[16];
    tampon: array[0..2] of byte;
    pos: cardinal;
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := 'abc.txt';
  NeoOpenFile(1, @nom, 0);
  NeoReadFile(1, word(@tampon), 3);             // 3,8
  pos := NeoTellPos(1);                         // File Tell
  NeoCloseFile(1);
  writeln('Position apres 3 octets lus : ', pos);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Position apres 3 octets lus : 3
NeoBASIC
10 ' Position apres avoir lu 3 octets (groupe 3, fonction 7)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 b = alloc(4) : m = 0 : while peek($ff00) : wend : poke $ff04, 1 : poke $ff05, a & 255 : poke $ff06, a >> 8 : poke $ff07, m : poke $ff01, 4 : poke $ff00, 3 : while peek($ff00) : wend
40 poke $ff04, 1 : poke $ff05, b & 255 : poke $ff06, b >> 8 : poke $ff07, 3 : poke $ff08, 0 : poke $ff01, 8 : poke $ff00, 3
50 while peek($ff00) : wend
60 poke $ff04, 1 : poke $ff01, 7 : poke $ff00, 3
70 while peek($ff00) : wend : p = peek($ff05) + 256 * peek($ff06)
80 close
90 print "Position apres 3 octets lus : ";p
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Position apres 3 octets lus : 3
Assembleur 65C02 (64tass)
; Position après avoir lu 3 octets (groupe 3, 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            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        lda #0
        jsr ouvrir
        jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #<tampon
        sta ControlPort+5
        lda #>tampon
        sta ControlPort+6
        lda #3
        sta ControlPort+7          ; lire 3 octets
        stz ControlPort+8
        lda #3
        ldx #8                     ; 3,8 : File Read
        jsr appel
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #3
        ldx #7                     ; fonction 7 : File Tell
        jsr appel
        lda ControlPort+5          ; P1 : position (poids faible)
        sta pos
        jsr fermer
        lda #<m
        ldx #>m
        jsr ecrire
        lda pos
        jsr decimal
        lda #13
        jmp WriteCharacter
; Ouvrir abc.txt sur le canal 1 dans le mode A.
ouvrir: pha
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<nom
        sta ControlPort+5          ; P1-P2 : nom
        lda #>nom
        sta ControlPort+6
        pla
        sta ControlPort+7          ; P3 : mode
        lda #3
        ldx #4                     ; 3,4 : File Open
        jmp appel

; Fermer le canal 1.
fermer: jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #3
        ldx #5                     ; 3,5 : File Close
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

tampon: .fill 3
pos:    .byte 0
m:      .text "Position apres 3 octets lus : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Position apres 3 octets lus : 3

3,8 File Read Officiel

Lit des octets d'un canal ouvert, à partir de sa position, vers la mémoire (ou la mémoire graphique avec l'adresse $FFFF).

Entrées
OctetsTypeRôle
P0uint8numéro du canal
P1-P2addrdestination, ou $FFFF pour la mémoire graphique
P3-P4uint16nombre d'octets demandés
Sorties
OctetsTypeRôle
P3-P4uint16nombre d'octets réellement lus (moins à la fin du fichier)

La position avance d'autant. Demander plus que ce qui reste n'est pas une erreur : P3-P4 dit combien d'octets sont venus.

Texte de la documentation du firmware (anglais)

Reads data from an opened file. On input:

Parameter:0 contains the file channel to operate on. Parameters:1,2 points to the destination in memory, or $FFFF to read into graphics memory. Parameters:3,4 contains the amount of data to read.

On output:

Parameters:3,4 is updated to contain the amount of data actually read.

Data is read from the current seek position, which is advanced after the read.

C (llvm-mos)
/* Lire tout le fichier, en demandant plus qu'il n'y a (groupe 3, fonction 8). */
#include <stdio.h>
#include <neo/api.h>

int main(void) {
    char tampon[21] = { 0 };
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_open(1, "abc.txt", NEO_FILE_READ);
    uint16_t n = neo_file_read(1, tampon, 20);  /* File Read : 20 demandés */
    neo_file_close(1);
    printf("Lu : %s (%u octets sur 20 demandes)\n", tampon, n);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lu : ABCDEFGH (8 octets sur 20 demandes)
Mad Pascal
// Lire tout le fichier, en demandant plus qu'il n'y a (groupe 3, fonction 8).
program lire;
uses crt, neo6502;
var texte, nom: string[16];
    tampon: string[20];
    n: word;
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := 'abc.txt';
  NeoOpenFile(1, @nom, 0);
  n := NeoReadFile(1, word(@tampon) + 1, 20);   // File Read : 20 demandés
  NeoCloseFile(1);
  tampon[0] := chr(n);                          // longueur de la chaîne Pascal
  writeln('Lu : ', tampon, ' (', n, ' octets sur 20 demandes)');
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lu : ABCDEFGH (8 octets sur 20 demandes)
NeoBASIC
10 ' Lire tout le fichier, en demandant plus qu'il n'y a (groupe 3, fonction 8)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 b = alloc(24) : m = 0 : while peek($ff00) : wend : poke $ff04, 1 : poke $ff05, a & 255 : poke $ff06, a >> 8 : poke $ff07, m : poke $ff01, 4 : poke $ff00, 3 : while peek($ff00) : wend
40 poke $ff04, 1 : poke $ff05, b & 255 : poke $ff06, b >> 8 : poke $ff07, 20 : poke $ff08, 0 : poke $ff01, 8 : poke $ff00, 3
50 while peek($ff00) : wend : n = peek($ff07) + 256 * peek($ff08)
60 close
70 s$ = "" : for i = 0 to n - 1 : s$ = s$ + chr$(peek(b + i)) : next i
80 print "Lu : ";s$;" (";n;" octets sur 20 demandes)"
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lu : ABCDEFGH (8 octets sur 20 demandes)
Assembleur 65C02 (64tass)
; Lire tout le fichier, en demandant plus qu'il n'y a (groupe 3, 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            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        lda #0
        jsr ouvrir
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<tampon
        sta ControlPort+5          ; P1-P2 : destination
        lda #>tampon
        sta ControlPort+6
        lda #20
        sta ControlPort+7          ; P3-P4 : 20 octets demandés
        stz ControlPort+8
        lda #3
        ldx #8                     ; fonction 8 : File Read
        jsr appel
        lda ControlPort+7          ; octets réellement lus
        sta lus
        jsr fermer
        lda #<m1
        ldx #>m1
        jsr ecrire
        lda #<tampon
        ldx #>tampon
        jsr ecrire
        lda #<m2
        ldx #>m2
        jsr ecrire
        lda lus
        jsr decimal
        lda #<m3
        ldx #>m3
        jmp ecrire
; Ouvrir abc.txt sur le canal 1 dans le mode A.
ouvrir: pha
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<nom
        sta ControlPort+5          ; P1-P2 : nom
        lda #>nom
        sta ControlPort+6
        pla
        sta ControlPort+7          ; P3 : mode
        lda #3
        ldx #4                     ; 3,4 : File Open
        jmp appel

; Fermer le canal 1.
fermer: jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #3
        ldx #5                     ; 3,5 : File Close
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

tampon: .fill 21                   ; zéros : la chaîne lue sera terminée
lus:    .byte 0
m1:     .text "Lu : ", 0
m2:     .text " (", 0
m3:     .text " octets sur 20 demandes)", 13, 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lu : ABCDEFGH (8 octets sur 20 demandes)

3,9 File Write Officiel

Écrit des octets de la mémoire dans un canal ouvert, à partir de sa position.

Entrées
OctetsTypeRôle
P0uint8numéro du canal
P1-P2addradresse des données
P3-P4uint16nombre d'octets
Sorties
OctetsTypeRôle
P3-P4uint16nombre d'octets réellement écrits

La position avance d'autant. L'écriture peut rester en tampon jusqu'à la fermeture (3,5).

Texte de la documentation du firmware (anglais)

Writes data to an opened file. On input:

Parameter:0 contains the file channel to operate on; Parameters:1,2 points to the data in memory; Parameters:3,4 contains the amount of data to write.

On output: Parameters:3,4 is updated to contain the amount of data actually written.

Data is written to the current seek position, which is advanced after the write.

C (llvm-mos)
/* Écrire 5 octets, fermer, vérifier la taille (groupe 3, fonction 9). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
    ControlPort.function = fonction;
    ControlPort.command = groupe;
    while (ControlPort.command)        /* attendre la fin */
        ;
}
static void libre(void) {              /* attendre que la boîte aux lettres soit libre */
    while (ControlPort.command)
        ;
}

static const uint8_t nom[] = "\x08" "neuf.txt";

int main(void) {
    neo_file_open(1, "neuf.txt", NEO_FILE_CREATE);
    uint32_t n = neo_file_write(1, "Salut", 5); /* File Write */
    neo_file_close(1);
    libre();
    ControlPort.params[0] = (uint16_t)nom & 0xFF;
    ControlPort.params[1] = (uint16_t)nom >> 8;
    api(3, 16);                                 /* 3,16 : taille en P0-P3 */
    printf("Ecrits : %lu, taille du fichier : %u\n", (unsigned long)n, ControlPort.params[0] | (ControlPort.params[1] << 8));
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Ecrits : 5, taille du fichier : 5
Mad Pascal
// Écrire 5 octets, fermer, vérifier la taille (groupe 3, fonction 9).
program ecrire;
uses crt, neo6502;
var nom, texte: string[16];
    n: word;
    taille: cardinal;
    attr: byte;
begin
  nom := 'neuf.txt';
  texte := 'Salut';
  NeoOpenFile(1, @nom, 3);
  n := NeoWriteFile(1, word(@texte) + 1, 5);    // File Write
  NeoCloseFile(1);
  NeoStatFile(@nom, taille, attr);              // 3,16
  writeln('Ecrits : ', n, ', taille du fichier : ', taille);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Ecrits : 5, taille du fichier : 5
NeoBASIC
10 ' Ecrire 5 octets, fermer, verifier la taille (groupe 3, fonction 9)
20 n$ = "neuf.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 d = alloc(8) : for i = 1 to 5 : poke d + i - 1, asc(mid$("Salut", i, 1)) : next i
40 m = 3 : while peek($ff00) : wend : poke $ff04, 1 : poke $ff05, a & 255 : poke $ff06, a >> 8 : poke $ff07, m : poke $ff01, 4 : poke $ff00, 3 : while peek($ff00) : wend
50 poke $ff04, 1 : poke $ff05, d & 255 : poke $ff06, d >> 8 : poke $ff07, 5 : poke $ff08, 0 : poke $ff01, 9 : poke $ff00, 3
60 while peek($ff00) : wend : n = peek($ff07)
70 close
80 while peek($ff00) : wend
90 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 16 : poke $ff00, 3
100 while peek($ff00) : wend : t = peek($ff04)
110 print "Ecrits : ";n;", taille du fichier : ";t
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Ecrits : 5, taille du fichier : 5
Assembleur 65C02 (64tass)
; Écrire 5 octets, fermer, vérifier la taille (groupe 3, 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:  lda #3
        jsr ouvrir_neuf
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<salut
        sta ControlPort+5          ; P1-P2 : données
        lda #>salut
        sta ControlPort+6
        lda #5
        sta ControlPort+7          ; P3-P4 : 5 octets
        stz ControlPort+8
        lda #3
        ldx #9                     ; fonction 9 : File Write
        jsr appel
        lda ControlPort+7
        sta ecrits
        jsr fermer
        jsr WaitMessage
        lda #<neuf
        sta ControlPort+4
        lda #>neuf
        sta ControlPort+5
        lda #3
        ldx #16                    ; 3,16 : taille
        jsr appel
        lda ControlPort+4
        sta taille
        lda #<m1
        ldx #>m1
        jsr ecrire
        lda ecrits
        jsr decimal
        lda #<m2
        ldx #>m2
        jsr ecrire
        lda taille
        jsr decimal
        lda #13
        jmp WriteCharacter

ouvrir_neuf:
        pha
        jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #<neuf
        sta ControlPort+5
        lda #>neuf
        sta ControlPort+6
        pla
        sta ControlPort+7
        lda #3
        ldx #4
        jmp appel
; Ouvrir abc.txt sur le canal 1 dans le mode A.
ouvrir: pha
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<nom
        sta ControlPort+5          ; P1-P2 : nom
        lda #>nom
        sta ControlPort+6
        pla
        sta ControlPort+7          ; P3 : mode
        lda #3
        ldx #4                     ; 3,4 : File Open
        jmp appel

; Fermer le canal 1.
fermer: jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #3
        ldx #5                     ; 3,5 : File Close
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

neuf:   .byte 8
        .text "neuf.txt"
salut:  .text "Salut"
ecrits: .byte 0
taille: .byte 0
m1:     .text "Ecrits : ", 0
m2:     .text ", taille du fichier : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Ecrits : 5, taille du fichier : 5

3,10 File Size Officiel

Donne la taille actuelle d'un fichier ouvert, écritures encore en tampon comprises.

Entrées
OctetsTypeRôle
P0uint8numéro du canal
Sorties
OctetsTypeRôle
P1-P4uint32taille en octets

Sur un fichier en cours d'écriture, 3,16 (qui lit le disque) peut donner une taille différente.

Texte de la documentation du firmware (anglais)

Returns the current size of an opened file. On input:

Parameter:0 contains the file channel to operate on.

On output: Parameters:1..4 contains the size of the file.

This call should be used on open files, and takes into account any buffered data which has not yet been written to disk. Consequently, this may return a different size than Function 3,16 "File Stat".

C (llvm-mos)
/* Taille d'un fichier ouvert (groupe 3, fonction 10). */
#include <stdio.h>
#include <neo/api.h>

int main(void) {
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_open(1, "abc.txt", NEO_FILE_READ);
    uint32_t taille = neo_file_size(1);         /* File Size */
    neo_file_close(1);
    printf("Taille du fichier ouvert : %lu\n", (unsigned long)taille);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Taille du fichier ouvert : 8
Mad Pascal
// Taille d'un fichier ouvert (groupe 3, fonction 10).
program taille;
uses crt, neo6502;
var texte, nom: string[16];
    t: cardinal;
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := 'abc.txt';
  NeoOpenFile(1, @nom, 0);
  t := NeoGetFileSize(1);                       // File Size
  NeoCloseFile(1);
  writeln('Taille du fichier ouvert : ', t);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Taille du fichier ouvert : 8
NeoBASIC
10 ' Taille d'un fichier ouvert (groupe 3, fonction 10)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 m = 0 : while peek($ff00) : wend : poke $ff04, 1 : poke $ff05, a & 255 : poke $ff06, a >> 8 : poke $ff07, m : poke $ff01, 4 : poke $ff00, 3 : while peek($ff00) : wend
40 poke $ff04, 1 : poke $ff01, 10 : poke $ff00, 3
50 while peek($ff00) : wend : t = peek($ff05) + 256 * peek($ff06)
60 close
70 print "Taille du fichier ouvert : ";t
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Taille du fichier ouvert : 8
Assembleur 65C02 (64tass)
; Taille d'un fichier ouvert (groupe 3, 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            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        lda #0
        jsr ouvrir
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #3
        ldx #10                    ; fonction 10 : File Size
        jsr appel
        lda ControlPort+5          ; P1 : taille (poids faible)
        sta taille
        jsr fermer
        lda #<m
        ldx #>m
        jsr ecrire
        lda taille
        jsr decimal
        lda #13
        jmp WriteCharacter
; Ouvrir abc.txt sur le canal 1 dans le mode A.
ouvrir: pha
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<nom
        sta ControlPort+5          ; P1-P2 : nom
        lda #>nom
        sta ControlPort+6
        pla
        sta ControlPort+7          ; P3 : mode
        lda #3
        ldx #4                     ; 3,4 : File Open
        jmp appel

; Fermer le canal 1.
fermer: jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #3
        ldx #5                     ; 3,5 : File Close
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

taille: .byte 0
m:      .text "Taille du fichier ouvert : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Taille du fichier ouvert : 8

3,11 File Set Size Officiel

Agrandit ou tronque un fichier ouvert à la taille voulue.

Entrées
OctetsTypeRôle
P0uint8numéro du canal
P1-P4uint32nouvelle taille

Sorties : aucune.

En Mad Pascal 1.7.8, NeoSetFileSize appelle la fonction 10 (lire la taille) au lieu de 11 : le fichier ne change pas. L'exemple Pascal fait l'appel directement.

Texte de la documentation du firmware (anglais)

Extends or truncates an opened file to a particular size. On input:

Parameter:0 contains the file channel to operate on; Parameters:1..4 contains the new size of the file.

C (llvm-mos)
/* Tronquer ABCDEFGH à 3 octets (groupe 3, fonction 11). */
#include <stdio.h>
#include <neo/api.h>

int main(void) {
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_open(1, "abc.txt", NEO_FILE_READ_WRITE);
    neo_file_set_size(1, 3);                    /* File Set Size */
    uint32_t taille = neo_file_size(1);         /* 3,10 */
    neo_file_close(1);
    printf("Taille apres troncature : %lu\n", (unsigned long)taille);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Taille apres troncature : 3
Mad Pascal
// Tronquer ABCDEFGH à 3 octets (groupe 3, fonction 11).
// NeoSetFileSize (Mad Pascal 1.7.8) appelle la fonction 10 : appel direct.
program tronquer;
uses crt, neo6502;
var texte, nom: string[16];
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := 'abc.txt';
  NeoOpenFile(1, @nom, 2);                      // lecture-écriture
  NeoWaitMessage;
  NeoMessage.params[0] := 1;                    // P0 : canal
  FI_offset := 3;                               // P1-P4 : nouvelle taille
  NeoSendMessage(3, 11);                        // File Set Size
  NeoWaitMessage;
  writeln('Taille apres troncature : ', NeoGetFileSize(1));
  NeoCloseFile(1);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Taille apres troncature : 3
NeoBASIC
10 ' Tronquer ABCDEFGH a 3 octets (groupe 3, fonction 11)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 m = 2 : while peek($ff00) : wend : poke $ff04, 1 : poke $ff05, a & 255 : poke $ff06, a >> 8 : poke $ff07, m : poke $ff01, 4 : poke $ff00, 3 : while peek($ff00) : wend
40 poke $ff04, 1 : poke $ff05, 3 : poke $ff06, 0 : poke $ff07, 0 : poke $ff08, 0 : poke $ff01, 11 : poke $ff00, 3
50 while peek($ff00) : wend
60 poke $ff04, 1 : poke $ff01, 10 : poke $ff00, 3
70 while peek($ff00) : wend : t = peek($ff05)
80 close
90 print "Taille apres troncature : ";t
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Taille apres troncature : 3
Assembleur 65C02 (64tass)
; Tronquer ABCDEFGH à 3 octets (groupe 3, 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            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        lda #2
        jsr ouvrir                 ; lecture-écriture
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #3
        sta ControlPort+5          ; P1-P4 : 3 octets
        stz ControlPort+6
        stz ControlPort+7
        stz ControlPort+8
        lda #3
        ldx #11                    ; fonction 11 : File Set Size
        jsr appel
        jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #3
        ldx #10                    ; 3,10 : taille
        jsr appel
        lda ControlPort+5
        sta taille
        jsr fermer
        lda #<m
        ldx #>m
        jsr ecrire
        lda taille
        jsr decimal
        lda #13
        jmp WriteCharacter
; Ouvrir abc.txt sur le canal 1 dans le mode A.
ouvrir: pha
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<nom
        sta ControlPort+5          ; P1-P2 : nom
        lda #>nom
        sta ControlPort+6
        pla
        sta ControlPort+7          ; P3 : mode
        lda #3
        ldx #4                     ; 3,4 : File Open
        jmp appel

; Fermer le canal 1.
fermer: jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #3
        ldx #5                     ; 3,5 : File Close
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

taille: .byte 0
m:      .text "Taille apres troncature : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Taille apres troncature : 3

3,12 File Rename Officiel

Renomme un fichier, éventuellement en le déplaçant dans un autre répertoire.

Entrées
OctetsTypeRôle
P0-P1addradresse de l'ancien nom (précédé de sa longueur)
P2-P3addradresse du nouveau nom (précédé de sa longueur)
Sorties
OctetsTypeRôle
erreuruint8non nul si le renommage a échoué
Texte de la documentation du firmware (anglais)

Renames a file. On input:

Parameters:0,1 points to the length-prefixed string for the old name; Parameters:2,3 points to the length-prefixed string for the new name.

Files may be renamed across directories.

C (llvm-mos)
/* Renommer abc.txt en xyz.txt (groupe 3, fonction 12). */
#include <stdio.h>
#include <neo/api.h>

int main(void) {
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_rename("abc.txt", "xyz.txt");      /* File Rename */
    printf("Renomme : abc.txt -> xyz.txt, erreur %u\n", neo_api_error());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Renomme : abc.txt -> xyz.txt, erreur 0
Mad Pascal
// Renommer abc.txt en xyz.txt (groupe 3, fonction 12).
program renommer;
uses crt, neo6502;
var texte, nom, nouveau: string[16];
    e: byte;
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := 'abc.txt';
  nouveau := 'xyz.txt';
  NeoRenameFile(@nom, @nouveau);                // File Rename
  e := NeoMessage.error;                        // à lire avant writeln, qui passe par l'API
  writeln('Renomme : abc.txt -> xyz.txt, erreur ', e);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Renomme : abc.txt -> xyz.txt, erreur 0
NeoBASIC
10 ' Renommer abc.txt en xyz.txt (groupe 3, fonction 12)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 b = a : n$ = "xyz.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
40 while peek($ff00) : wend
50 poke $ff04, b & 255 : poke $ff05, b >> 8 : poke $ff06, a & 255 : poke $ff07, a >> 8 : poke $ff01, 12 : poke $ff00, 3
60 while peek($ff00) : wend : e = peek($ff02)
70 print "Renomme : abc.txt -> xyz.txt, erreur ";e
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Renomme : abc.txt -> xyz.txt, erreur 0
Assembleur 65C02 (64tass)
; Renommer abc.txt en xyz.txt (groupe 3, 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:
        jsr WaitMessage            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        jsr WaitMessage
        lda #<nom
        sta ControlPort+4          ; P0-P1 : ancien nom
        lda #>nom
        sta ControlPort+5
        lda #<xyz
        sta ControlPort+6          ; P2-P3 : nouveau nom
        lda #>xyz
        sta ControlPort+7
        lda #3
        ldx #12                    ; fonction 12 : File Rename
        jsr appel
        lda ControlPort+2
        pha
        lda #<m
        ldx #>m
        jsr ecrire
        pla
        jsr decimal
        lda #13
        jmp WriteCharacter
; Ouvrir abc.txt sur le canal 1 dans le mode A.
ouvrir: pha
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<nom
        sta ControlPort+5          ; P1-P2 : nom
        lda #>nom
        sta ControlPort+6
        pla
        sta ControlPort+7          ; P3 : mode
        lda #3
        ldx #4                     ; 3,4 : File Open
        jmp appel

; Fermer le canal 1.
fermer: jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #3
        ldx #5                     ; 3,5 : File Close
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

xyz:    .byte 7
        .text "xyz.txt"
m:      .text "Renomme : abc.txt -> xyz.txt, erreur ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Renomme : abc.txt -> xyz.txt, erreur 0

3,13 File Delete Officiel

Supprime un fichier, ou un répertoire vide.

Entrées
OctetsTypeRôle
P0-P1addradresse du nom (précédé de sa longueur)
Sorties
OctetsTypeRôle
erreuruint8non nul si la suppression a échoué

Supprimer un fichier ouvert a un comportement indéfini. L'exemple vérifie avec 3,16 que le fichier a disparu (erreur $11 : fichier absent).

Texte de la documentation du firmware (anglais)

Deletes a file or directory. On input:

Parameters:0,1 points to the length-prefixed filename string.

Deleting a file which is open has undefined behaviour. Directories may only be deleted if they are empty.

C (llvm-mos)
/* Supprimer un fichier, puis vérifier qu'il a disparu (groupe 3, fonction 13). */
#include <stdio.h>
#include <neo/api.h>

int main(void) {
    neo_file_stat_t st;
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_delete("abc.txt");                 /* File Delete */
    neo_file_stat("abc.txt", &st);              /* 3,16 : doit échouer */
    printf("Supprime, puis 3,16 donne l'erreur %u\n", neo_api_error());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Supprime, puis 3,16 donne l'erreur 17
Mad Pascal
// Supprimer un fichier, puis vérifier qu'il a disparu (groupe 3, fonction 13).
program supprimer;
uses crt, neo6502;
var texte, nom: string[16];
    e: byte;
    taille: cardinal;
    attr: byte;
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := 'abc.txt';
  NeoDeleteFile(@nom);                          // File Delete
  NeoStatFile(@nom, taille, attr);              // 3,16 : doit échouer
  e := NeoMessage.error;                        // à lire avant writeln, qui passe par l'API
  writeln('Supprime, puis 3,16 donne l''erreur ', e);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Supprime, puis 3,16 donne l'erreur 17
NeoBASIC
10 ' Supprimer un fichier, puis verifier qu'il a disparu (groupe 3, fonction 13)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 while peek($ff00) : wend
40 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 13 : poke $ff00, 3
50 while peek($ff00) : wend
60 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 16 : poke $ff00, 3
70 while peek($ff00) : wend : e = peek($ff02)
80 print "Supprime, puis 3,16 donne l'erreur ";e
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Supprime, puis 3,16 donne l'erreur 17
Assembleur 65C02 (64tass)
; Supprimer un fichier, puis vérifier qu'il a disparu (groupe 3, 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:
        jsr WaitMessage            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        ldx #13                    ; fonction 13 : File Delete
        jsr sur_nom
        ldx #16                    ; 3,16 : doit échouer
        jsr sur_nom
        lda ControlPort+2
        pha
        lda #<m
        ldx #>m
        jsr ecrire
        pla
        jsr decimal
        lda #13
        jmp WriteCharacter

sur_nom:                           ; X = fonction du groupe 3, sur abc.txt
        jsr WaitMessage
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #3
        jmp appel
; Ouvrir abc.txt sur le canal 1 dans le mode A.
ouvrir: pha
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<nom
        sta ControlPort+5          ; P1-P2 : nom
        lda #>nom
        sta ControlPort+6
        pla
        sta ControlPort+7          ; P3 : mode
        lda #3
        ldx #4                     ; 3,4 : File Open
        jmp appel

; Fermer le canal 1.
fermer: jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #3
        ldx #5                     ; 3,5 : File Close
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

m:      .text "Supprime, puis 3,16 donne l'erreur ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Supprime, puis 3,16 donne l'erreur 17

3,14 Create Directory Officiel

Crée un répertoire.

Entrées
OctetsTypeRôle
P0-P1addradresse du nom (précédé de sa longueur)
Sorties
OctetsTypeRôle
erreuruint8non nul si la création a échoué (répertoire déjà là, par exemple)

L'exemple vérifie avec 3,16 que le nom créé porte le bit « répertoire » (bit 0 des attributs). En C, 3,16 est appelé directement (neo_file_stat de llvm-mos rend des valeurs fausses, voir 3,16).

Texte de la documentation du firmware (anglais)

Creates a new directory. On input:

Parameters:0,1 points to the length-prefixed filename string.

C (llvm-mos)
/* Créer un répertoire, puis vérifier son attribut (groupe 3, fonction 14). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
    ControlPort.function = fonction;
    ControlPort.command = groupe;
    while (ControlPort.command)        /* attendre la fin */
        ;
}
static void libre(void) {              /* attendre que la boîte aux lettres soit libre */
    while (ControlPort.command)
        ;
}

static const uint8_t rep[] = "\x03" "rep";

int main(void) {
    neo_file_mkdir("rep");                      /* Create Directory */
    libre();
    ControlPort.params[0] = (uint16_t)rep & 0xFF;
    ControlPort.params[1] = (uint16_t)rep >> 8;
    api(3, 16);                                 /* 3,16 : attributs en P4 */
    printf("Repertoire cree, bit repertoire : %u\n", ControlPort.params[4] & 1);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Repertoire cree, bit repertoire : 1
Mad Pascal
// Créer un répertoire, puis vérifier son attribut (groupe 3, fonction 14).
program creer;
uses crt, neo6502;
var rep: string[16];
    taille: cardinal;
    attr: byte;
begin
  rep := 'rep';
  NeoCreateDirectory(@rep);                     // Create Directory
  NeoStatFile(@rep, taille, attr);              // 3,16
  writeln('Repertoire cree, bit repertoire : ', attr and FI_ATTR_DIRECTORY);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Repertoire cree, bit repertoire : 1
NeoBASIC
10 ' Creer un repertoire, puis verifier son attribut (groupe 3, fonction 14)
20 n$ = "rep" : a = alloc(8) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 while peek($ff00) : wend
40 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 14 : poke $ff00, 3
50 while peek($ff00) : wend
60 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 16 : poke $ff00, 3
70 while peek($ff00) : wend : t = peek($ff08) & 1
80 print "Repertoire cree, bit repertoire : ";t
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Repertoire cree, bit repertoire : 1
Assembleur 65C02 (64tass)
; Créer un répertoire, puis vérifier son attribut (groupe 3, 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 #<rep
        ldx #>rep
        ldy #14                    ; fonction 14 : Create Directory
        jsr sur_nom
        lda #<rep
        ldx #>rep
        ldy #16                    ; 3,16 : attributs en P4
        jsr sur_nom
        lda ControlPort+8
        and #1                     ; bit 0 : répertoire
        pha
        lda #<m
        ldx #>m
        jsr ecrire
        pla
        jsr decimal
        lda #13
        jmp WriteCharacter

; Appel du groupe 3, fonction Y, avec en P0-P1 l'adresse du nom donnée par A (poids faible) et X.
sur_nom:
        pha
        jsr WaitMessage
        pla
        sta ControlPort+4
        stx ControlPort+5
        tya
        tax
        lda #3
        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

rep:    .byte 3
        .text "rep"
m:      .text "Repertoire cree, bit repertoire : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Repertoire cree, bit repertoire : 1

3,15 Change Directory Officiel

Change le répertoire courant.

Entrées
OctetsTypeRôle
P0-P1addradresse du chemin (précédé de sa longueur)
Sorties
OctetsTypeRôle
erreuruint8non nul si le répertoire n'existe pas

Les noms sans chemin des autres fonctions du groupe se rapportent ensuite à ce répertoire. « .. » remonte d'un niveau.

Texte de la documentation du firmware (anglais)

Changes the current working directory. On input:

Parameters:0,1 points to the length-prefixed path string.

C (llvm-mos)
/* Créer un répertoire et s'y placer (groupe 3, fonction 15). */
#include <stdio.h>
#include <neo/api.h>

static char cwd[33];

static const char *courant(void) {
    neo_file_get_cwd(cwd, 32);                  /* 3,23 : chaîne précédée de sa longueur */
    cwd[(uint8_t)cwd[0] + 1] = 0;
    return cwd + 1;
}

int main(void) {
    neo_file_mkdir("rep");                      /* 3,14 */
    neo_file_chdir("rep");                      /* Change Directory */
    printf("Repertoire courant : %s\n", courant());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Repertoire courant : /rep
Mad Pascal
// Créer un répertoire et s'y placer (groupe 3, fonction 15).
program chdir;
uses crt, neo6502;
var rep: string[16];

function courant: string;
var cwd: string[32];
begin
  NeoWaitMessage;
  wordParams[0] := word(@cwd);                  // P0-P1 : tampon
  NeoMessage.params[2] := 32;                   // P2 : longueur maximale
  NeoSendMessage(3, 23);                        // 3,23 : Get Current Working Directory
  NeoWaitMessage;
  result := cwd;
end;

begin
  rep := 'rep';
  NeoCreateDirectory(@rep);                     // 3,14
  NeoChangeDirectory(@rep);                     // Change Directory
  writeln('Repertoire courant : ', courant);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Repertoire courant : /rep
NeoBASIC
10 ' Creer un repertoire et s'y placer (groupe 3, fonction 15)
20 n$ = "rep" : a = alloc(8) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 while peek($ff00) : wend
40 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 14 : poke $ff00, 3
50 while peek($ff00) : wend
60 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 15 : poke $ff00, 3
70 while peek($ff00) : wend
80 b = alloc(34) : poke $ff04, b & 255 : poke $ff05, b >> 8 : poke $ff06, 32 : poke $ff01, 23 : poke $ff00, 3
90 while peek($ff00) : wend : s$ = "" : for i = 1 to peek(b) : s$ = s$ + chr$(peek(b + i)) : next i
100 print "Repertoire courant : ";s$
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Repertoire courant : /rep
Assembleur 65C02 (64tass)
; Créer un répertoire et s'y placer (groupe 3, fonction 15).
        .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 #<rep
        ldx #>rep
        ldy #14                    ; 3,14 : Create Directory
        jsr sur_nom
        lda #<rep
        ldx #>rep
        ldy #15                    ; fonction 15 : Change Directory
        jsr sur_nom
        jsr courant
        lda #<m
        ldx #>m
        jsr ecrire
        lda #<cwd
        ldx #>cwd
        jsr pecrire
        lda #13
        jmp WriteCharacter

; Répertoire courant dans cwd (précédé de sa longueur).
courant:
        jsr WaitMessage
        lda #<cwd
        sta ControlPort+4          ; P0-P1 : tampon
        lda #>cwd
        sta ControlPort+5
        lda #32
        sta ControlPort+6          ; P2 : longueur maximale
        lda #3
        ldx #23                    ; 3,23 : Get Current Working Directory
        jmp appel
cwd:    .fill 34

; Appel du groupe 3, fonction Y, avec en P0-P1 l'adresse du nom donnée par A (poids faible) et X.
sur_nom:
        pha
        jsr WaitMessage
        pla
        sta ControlPort+4
        stx ControlPort+5
        tya
        tax
        lda #3
        jmp appel

; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
        sta ptr
        stx ptr+1
        lda (ptr)
        sta reste
        ldy #1
_p:     lda reste
        beq _pf
        lda (ptr),y
        jsr WriteCharacter
        iny
        dec reste
        bra _p
_pf:    rts
reste:  .byte 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

rep:    .byte 3
        .text "rep"
m:      .text "Repertoire courant : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Repertoire courant : /rep

3,16 File Stat Officiel

Donne la taille et les attributs d'un fichier, par son nom.

Entrées
OctetsTypeRôle
P0-P1addradresse du nom (précédé de sa longueur)
Sorties
OctetsTypeRôle
P0-P3uint32taille en octets
P4uint8attributs : bit 0 répertoire, 1 système, 2 archive, 3 lecture seule, 4 caché
erreuruint8non nul si le fichier n'existe pas

Sur un fichier ouvert en écriture, la taille peut ne pas compter ce qui est encore en tampon (3,10 le compte). En NeoBASIC, exists("nom") fait cet appel et rend vrai ou faux. En C, neo_file_stat de llvm-mos (compilateur c798c31) rend une taille et des attributs faux : l'exemple fait l'appel directement.

Mots-clés NeoBASIC qui font cet appel : exists()

Texte de la documentation du firmware (anglais)

Retrieves information about a file by name. On input:

Parameters:0,1 points to the length-prefixed filename string.

Parameters:0..3 contains the length of the file; Parameter:4 contains the attributes bit-field of the file.

If the file is open for writing, this may not return the correct size due to buffered data not having been flushed to disk.

File attributes are a bitfield as follows: 0,0,0,Hidden, Read Only, Archive, System, Directory.

C (llvm-mos)
/* Taille et attributs d'un fichier (groupe 3, fonction 16). */
/* neo_file_stat (llvm-mos, compilateur c798c31) rend des valeurs fausses : appel direct. */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
    ControlPort.function = fonction;
    ControlPort.command = groupe;
    while (ControlPort.command)        /* attendre la fin */
        ;
}
static void libre(void) {              /* attendre que la boîte aux lettres soit libre */
    while (ControlPort.command)
        ;
}

static const uint8_t nom[] = "\x07" "abc.txt";

int main(void) {
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    libre();
    ControlPort.params[0] = (uint16_t)nom & 0xFF;   /* P0-P1 : nom */
    ControlPort.params[1] = (uint16_t)nom >> 8;
    api(3, 16);                                     /* File Stat */
    printf("abc.txt : %u octets, repertoire : %u\n",
           ControlPort.params[0] | (ControlPort.params[1] << 8), ControlPort.params[4] & 1);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt : 8 octets, repertoire : 0
Mad Pascal
// Taille et attributs d'un fichier (groupe 3, fonction 16).
program stat;
uses crt, neo6502;
var texte, nom: string[16];
    taille: cardinal;
    attr: byte;
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := 'abc.txt';
  NeoStatFile(@nom, taille, attr);              // File Stat
  writeln('abc.txt : ', taille, ' octets, repertoire : ', attr and FI_ATTR_DIRECTORY);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt : 8 octets, repertoire : 0
NeoBASIC
10 ' Taille et attributs d'un fichier (groupe 3, fonction 16)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 if exists("abc.txt")
40 while peek($ff00) : wend
50 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 16 : poke $ff00, 3
60 while peek($ff00) : wend : t = peek($ff04) + 256 * peek($ff05) : r = peek($ff08) & 1
70 print "abc.txt : ";t;" octets, repertoire : ";r
80 endif
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt : 8 octets, repertoire : 0
Assembleur 65C02 (64tass)
; Taille et attributs d'un fichier (groupe 3, 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            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        lda #<nom
        ldx #>nom
        ldy #16                    ; fonction 16 : File Stat
        jsr sur_nom
        lda ControlPort+4          ; P0 : taille (poids faible)
        sta taille
        lda ControlPort+8          ; P4 : attributs
        and #1
        sta dir
        lda #<m1
        ldx #>m1
        jsr ecrire
        lda taille
        jsr decimal
        lda #<m2
        ldx #>m2
        jsr ecrire
        lda dir
        jsr decimal
        lda #13
        jmp WriteCharacter

; Appel du groupe 3, fonction Y, avec en P0-P1 l'adresse du nom donnée par A (poids faible) et X.
sur_nom:
        pha
        jsr WaitMessage
        pla
        sta ControlPort+4
        stx ControlPort+5
        tya
        tax
        lda #3
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

taille: .byte 0
dir:    .byte 0
m1:     .text "abc.txt : ", 0
m2:     .text " octets, repertoire : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt : 8 octets, repertoire : 0

3,17 Open Directory Officiel

Ouvre un répertoire pour en lire les entrées une à une (3,18).

Entrées
OctetsTypeRôle
P0-P1addradresse du chemin (précédé de sa longueur) ; « . » pour le répertoire courant
Sorties
OctetsTypeRôle
erreuruint8non nul si le répertoire n'existe pas

Un seul répertoire ouvert à la fois : en ouvrir un autre ferme le premier. Un répertoire ouvert peut empêcher sa suppression ; fermez-le (3,19) après usage.

Texte de la documentation du firmware (anglais)

Opens a directory for enumeration. On input:

Parameters:0,1 points to the length-prefixed filename string.

Only one directory at a time may be opened. If a directory is already open when this call is made, it is automatically closed. However, an open directory may make it impossible to delete the directory; so closing the directory after use is good practice.

C (llvm-mos)
/* Lister le répertoire courant (groupe 3, fonction 17 : Open Directory). */
#include <stdio.h>
#include <neo/api.h>

int main(void) {
    char nom[32];
    neo_file_stat_t st;
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_opendir(".");                      /* 3,17 : Open Directory */
    for (;;) {
        nom[0] = sizeof nom - 1;                /* capacité, lue par le firmware */
        neo_file_readdir(nom, &st);             /* 3,18 : Read Directory */
        if (neo_api_error())                    /* plus d'entrée */
            break;
        printf("%s %lu\n", nom, (unsigned long)st.size);
    }
    neo_file_closedir();                        /* 3,19 : Close Directory */
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt 8
PROG.NEO 4642
Mad Pascal
// Lister le répertoire courant (groupe 3, fonction 17 : Open Directory).
program liste;
uses crt, neo6502;
var texte, nom: string[16];
    f: string[31];
    taille: cardinal;
    attr: byte;
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := '.';
  NeoOpenDirectory(@nom);                       // 3,17 : Open Directory
  repeat
    f[0] := chr(31);                            // capacité, lue par le firmware
    if not NeoReadDirectory(f, taille, attr) then break;   // 3,18 : Read Directory
    writeln(f, ' ', taille);
  until false;
  NeoCloseDirectory;                            // 3,19 : Close Directory
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt 8
PROG.NEO 741
NeoBASIC
10 ' Lister le repertoire courant (groupe 3, fonction 17 : Open Directory).
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 n$ = "." : a = alloc(4) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
40 while peek($ff00) : wend
50 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 17 : poke $ff00, 3 : ' Open Directory
60 b = alloc(34) : e = 0
70 while e = 0
80 poke b, 32 : while peek($ff00) : wend : ' capacite, lue par le firmware
90 poke $ff04, b & 255 : poke $ff05, b >> 8 : poke $ff01, 18 : poke $ff00, 3 : ' Read Directory
100 while peek($ff00) : wend : e = peek($ff02) : t = peek($ff06) + 256 * peek($ff07)
110 if e = 0
120 s$ = "" : for i = 1 to peek(b) : s$ = s$ + chr$(peek(b + i)) : next i
130 print s$;" ";t
140 endif
150 wend
160 while peek($ff00) : wend : poke $ff01, 19 : poke $ff00, 3 : ' Close Directory
170 while peek($ff00) : wend
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt 8
prog.bas 925
boot 0
Assembleur 65C02 (64tass)
; Lister le répertoire courant (groupe 3, fonction 17 : Open Directory).
        .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            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        lda #<point
        ldx #>point
        ldy #17                    ; 3,17 : Open Directory
        jsr sur_nom
_suiv:  lda #32
        sta fichier                ; capacité, lue par le firmware
        lda #<fichier
        ldx #>fichier
        ldy #18                    ; 3,18 : Read Directory
        jsr sur_nom
        lda ControlPort+2
        bne _fin                   ; erreur : plus d'entrée
        lda ControlPort+6          ; P2 : taille (poids faible)
        sta taille
        lda #<fichier
        ldx #>fichier
        jsr pecrire
        lda #' '
        jsr WriteCharacter
        lda taille
        jsr decimal
        lda #13
        jsr WriteCharacter
        bra _suiv
_fin:   jsr WaitMessage
        lda #3
        ldx #19                    ; 3,19 : Close Directory
        jmp appel

; Appel du groupe 3, fonction Y, avec en P0-P1 l'adresse du nom donnée par A (poids faible) et X.
sur_nom:
        pha
        jsr WaitMessage
        pla
        sta ControlPort+4
        stx ControlPort+5
        tya
        tax
        lda #3
        jmp appel

; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
        sta ptr
        stx ptr+1
        lda (ptr)
        sta reste
        ldy #1
_p:     lda reste
        beq _pf
        lda (ptr),y
        jsr WriteCharacter
        iny
        dec reste
        bra _p
_pf:    rts
reste:  .byte 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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

point:  .byte 1
        .text "."
taille: .byte 0
fichier: .fill 34
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt 8
PROG.NEO 13

3,18 Read Directory Officiel

Lit l'entrée suivante du répertoire ouvert : nom, taille, attributs.

Entrées
OctetsTypeRôle
P0-P1addradresse du tampon du nom ; son premier octet donne sa capacité
Sorties
OctetsTypeRôle
tamponstringnom (précédé de sa longueur), sans chemin
P2-P5uint32taille en octets
P6uint8attributs, comme 3,16
erreuruint8non nul quand il n'y a plus d'entrée

Le firmware lit la capacité du tampon dans son premier octet : il faut l'y mettre avant chaque appel. Avec 0, l'entrée est consommée mais le nom revient vide. C'est aussi vrai pour neo_file_readdir de llvm-mos (le tableau passé doit commencer par sa capacité) et pour NeoReadDirectory de Mad Pascal (la longueur actuelle de la chaîne sert de capacité : une chaîne vide donne un nom vide). Les exemples le font.

Texte de la documentation du firmware (anglais)

Reads an item from the currently open directory. On input:

Parameters:0,1 points to a length-prefixed buffer for returning the filename.

Parameters:0,1 is unchanged, but the buffer is updated to contain the length-prefixed filename (without any leading path); Parameters:2..5 contains the length of the file; Parameter:6 contains the file attributes, as described by Function 3,16 "File Stat".

If there are no more items to read, this call fails and an error is flagged.

C (llvm-mos)
/* Lister le répertoire courant (groupe 3, fonction 18 : Read Directory). */
#include <stdio.h>
#include <neo/api.h>

int main(void) {
    char nom[32];
    neo_file_stat_t st;
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_opendir(".");                      /* 3,17 : Open Directory */
    for (;;) {
        nom[0] = sizeof nom - 1;                /* capacité, lue par le firmware */
        neo_file_readdir(nom, &st);             /* 3,18 : Read Directory */
        if (neo_api_error())                    /* plus d'entrée */
            break;
        printf("%s %lu\n", nom, (unsigned long)st.size);
    }
    neo_file_closedir();                        /* 3,19 : Close Directory */
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt 8
PROG.NEO 4642
Mad Pascal
// Lister le répertoire courant (groupe 3, fonction 18 : Read Directory).
program liste;
uses crt, neo6502;
var texte, nom: string[16];
    f: string[31];
    taille: cardinal;
    attr: byte;
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := '.';
  NeoOpenDirectory(@nom);                       // 3,17 : Open Directory
  repeat
    f[0] := chr(31);                            // capacité, lue par le firmware
    if not NeoReadDirectory(f, taille, attr) then break;   // 3,18 : Read Directory
    writeln(f, ' ', taille);
  until false;
  NeoCloseDirectory;                            // 3,19 : Close Directory
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt 8
PROG.NEO 741
NeoBASIC
10 ' Lister le repertoire courant (groupe 3, fonction 18 : Read Directory).
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 n$ = "." : a = alloc(4) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
40 while peek($ff00) : wend
50 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 17 : poke $ff00, 3 : ' Open Directory
60 b = alloc(34) : e = 0
70 while e = 0
80 poke b, 32 : while peek($ff00) : wend : ' capacite, lue par le firmware
90 poke $ff04, b & 255 : poke $ff05, b >> 8 : poke $ff01, 18 : poke $ff00, 3 : ' Read Directory
100 while peek($ff00) : wend : e = peek($ff02) : t = peek($ff06) + 256 * peek($ff07)
110 if e = 0
120 s$ = "" : for i = 1 to peek(b) : s$ = s$ + chr$(peek(b + i)) : next i
130 print s$;" ";t
140 endif
150 wend
160 while peek($ff00) : wend : poke $ff01, 19 : poke $ff00, 3 : ' Close Directory
170 while peek($ff00) : wend
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt 8
prog.bas 925
boot 0
Assembleur 65C02 (64tass)
; Lister le répertoire courant (groupe 3, fonction 18 : Read Directory).
        .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            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        lda #<point
        ldx #>point
        ldy #17                    ; 3,17 : Open Directory
        jsr sur_nom
_suiv:  lda #32
        sta fichier                ; capacité, lue par le firmware
        lda #<fichier
        ldx #>fichier
        ldy #18                    ; 3,18 : Read Directory
        jsr sur_nom
        lda ControlPort+2
        bne _fin                   ; erreur : plus d'entrée
        lda ControlPort+6          ; P2 : taille (poids faible)
        sta taille
        lda #<fichier
        ldx #>fichier
        jsr pecrire
        lda #' '
        jsr WriteCharacter
        lda taille
        jsr decimal
        lda #13
        jsr WriteCharacter
        bra _suiv
_fin:   jsr WaitMessage
        lda #3
        ldx #19                    ; 3,19 : Close Directory
        jmp appel

; Appel du groupe 3, fonction Y, avec en P0-P1 l'adresse du nom donnée par A (poids faible) et X.
sur_nom:
        pha
        jsr WaitMessage
        pla
        sta ControlPort+4
        stx ControlPort+5
        tya
        tax
        lda #3
        jmp appel

; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
        sta ptr
        stx ptr+1
        lda (ptr)
        sta reste
        ldy #1
_p:     lda reste
        beq _pf
        lda (ptr),y
        jsr WriteCharacter
        iny
        dec reste
        bra _p
_pf:    rts
reste:  .byte 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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

point:  .byte 1
        .text "."
taille: .byte 0
fichier: .fill 34
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt 8
PROG.NEO 13

3,19 Close Directory Officiel

Ferme le répertoire ouvert par 3,17.

Entrées : aucune.

Sorties : aucune.

Texte de la documentation du firmware (anglais)

Closes any directory opened previously by Function 3,17 "Open Directory".

C (llvm-mos)
/* Lister le répertoire courant (groupe 3, fonction 19 : Close Directory). */
#include <stdio.h>
#include <neo/api.h>

int main(void) {
    char nom[32];
    neo_file_stat_t st;
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_opendir(".");                      /* 3,17 : Open Directory */
    for (;;) {
        nom[0] = sizeof nom - 1;                /* capacité, lue par le firmware */
        neo_file_readdir(nom, &st);             /* 3,18 : Read Directory */
        if (neo_api_error())                    /* plus d'entrée */
            break;
        printf("%s %lu\n", nom, (unsigned long)st.size);
    }
    neo_file_closedir();                        /* 3,19 : Close Directory */
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt 8
PROG.NEO 4642
Mad Pascal
// Lister le répertoire courant (groupe 3, fonction 19 : Close Directory).
program liste;
uses crt, neo6502;
var texte, nom: string[16];
    f: string[31];
    taille: cardinal;
    attr: byte;
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := '.';
  NeoOpenDirectory(@nom);                       // 3,17 : Open Directory
  repeat
    f[0] := chr(31);                            // capacité, lue par le firmware
    if not NeoReadDirectory(f, taille, attr) then break;   // 3,18 : Read Directory
    writeln(f, ' ', taille);
  until false;
  NeoCloseDirectory;                            // 3,19 : Close Directory
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt 8
PROG.NEO 741
NeoBASIC
10 ' Lister le repertoire courant (groupe 3, fonction 19 : Close Directory).
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 n$ = "." : a = alloc(4) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
40 while peek($ff00) : wend
50 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 17 : poke $ff00, 3 : ' Open Directory
60 b = alloc(34) : e = 0
70 while e = 0
80 poke b, 32 : while peek($ff00) : wend : ' capacite, lue par le firmware
90 poke $ff04, b & 255 : poke $ff05, b >> 8 : poke $ff01, 18 : poke $ff00, 3 : ' Read Directory
100 while peek($ff00) : wend : e = peek($ff02) : t = peek($ff06) + 256 * peek($ff07)
110 if e = 0
120 s$ = "" : for i = 1 to peek(b) : s$ = s$ + chr$(peek(b + i)) : next i
130 print s$;" ";t
140 endif
150 wend
160 while peek($ff00) : wend : poke $ff01, 19 : poke $ff00, 3 : ' Close Directory
170 while peek($ff00) : wend
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt 8
prog.bas 926
boot 0
Assembleur 65C02 (64tass)
; Lister le répertoire courant (groupe 3, fonction 19 : Close Directory).
        .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            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        lda #<point
        ldx #>point
        ldy #17                    ; 3,17 : Open Directory
        jsr sur_nom
_suiv:  lda #32
        sta fichier                ; capacité, lue par le firmware
        lda #<fichier
        ldx #>fichier
        ldy #18                    ; 3,18 : Read Directory
        jsr sur_nom
        lda ControlPort+2
        bne _fin                   ; erreur : plus d'entrée
        lda ControlPort+6          ; P2 : taille (poids faible)
        sta taille
        lda #<fichier
        ldx #>fichier
        jsr pecrire
        lda #' '
        jsr WriteCharacter
        lda taille
        jsr decimal
        lda #13
        jsr WriteCharacter
        bra _suiv
_fin:   jsr WaitMessage
        lda #3
        ldx #19                    ; 3,19 : Close Directory
        jmp appel

; Appel du groupe 3, fonction Y, avec en P0-P1 l'adresse du nom donnée par A (poids faible) et X.
sur_nom:
        pha
        jsr WaitMessage
        pla
        sta ControlPort+4
        stx ControlPort+5
        tya
        tax
        lda #3
        jmp appel

; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
        sta ptr
        stx ptr+1
        lda (ptr)
        sta reste
        ldy #1
_p:     lda reste
        beq _pf
        lda (ptr),y
        jsr WriteCharacter
        iny
        dec reste
        bra _p
_pf:    rts
reste:  .byte 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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

point:  .byte 1
        .text "."
taille: .byte 0
fichier: .fill 34
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt 8
PROG.NEO 13

3,20 Copy File Officiel

Copie un fichier sous un autre nom.

Entrées
OctetsTypeRôle
P0-P1addradresse du nom d'origine (précédé de sa longueur)
P2-P3addradresse du nom de la copie (précédé de sa longueur)
Sorties
OctetsTypeRôle
erreuruint8non nul si la copie a échoué

Fichiers seuls : un répertoire ne se copie pas.

Texte de la documentation du firmware (anglais)

Copies a file. On input:

Parameters:0,1 points to the length-prefixed old filename; Parameters:2,3 points to the length-prefixed new filename.

Only single files may be copied, not directories.

C (llvm-mos)
/* Copier abc.txt, puis relire la copie (groupe 3, fonction 20). */
#include <stdio.h>
#include <neo/api.h>

int main(void) {
    char relu[9] = { 0 };
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_copy("abc.txt", "copie.txt");      /* Copy File */
    neo_file_load("copie.txt", relu);           /* 3,2 */
    printf("Copie : %s\n", relu);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Copie : ABCDEFGH
Mad Pascal
// Copier abc.txt, puis relire la copie (groupe 3, fonction 20).
program copier;
uses crt, neo6502;
var texte, nom, copie, relu: string[16];
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := 'abc.txt';
  copie := 'copie.txt';
  NeoCopyFile(@nom, @copie);                    // Copy File
  NeoLoad('copie.txt', word(@relu) + 1);        // 3,2
  relu[0] := chr(8);
  writeln('Copie : ', relu);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Copie : ABCDEFGH
NeoBASIC
10 ' Copier abc.txt, puis relire la copie (groupe 3, fonction 20)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 c = a : n$ = "copie.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
40 while peek($ff00) : wend
50 poke $ff04, c & 255 : poke $ff05, c >> 8 : poke $ff06, a & 255 : poke $ff07, a >> 8 : poke $ff01, 20 : poke $ff00, 3
60 while peek($ff00) : wend
70 r = alloc(16) : load "copie.txt", r
80 s$ = "" : for i = 0 to 7 : s$ = s$ + chr$(peek(r + i)) : next i
90 print "Copie : ";s$
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Copie : ABCDEFGH
Assembleur 65C02 (64tass)
; Copier abc.txt, puis relire la copie (groupe 3, 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:
        jsr WaitMessage            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        jsr WaitMessage
        lda #<nom
        sta ControlPort+4          ; P0-P1 : nom d'origine
        lda #>nom
        sta ControlPort+5
        lda #<copie
        sta ControlPort+6          ; P2-P3 : nom de la copie
        lda #>copie
        sta ControlPort+7
        lda #3
        ldx #20                    ; fonction 20 : Copy File
        jsr appel
        jsr WaitMessage
        lda #<copie
        sta ControlPort+4
        lda #>copie
        sta ControlPort+5
        lda #<relu
        sta ControlPort+6          ; P2-P3 : destination
        lda #>relu
        sta ControlPort+7
        lda #3
        ldx #2                     ; 3,2 : Load File
        jsr appel
        lda #<m
        ldx #>m
        jsr ecrire
        lda #<relu
        ldx #>relu
        jsr ecrire
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

copie:  .byte 9
        .text "copie.txt"
relu:   .fill 9                    ; zéros : la chaîne relue sera terminée
m:      .text "Copie : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Copie : ABCDEFGH

3,21 Set file attributes Officiel

Change les attributs d'un fichier (lecture seule, caché, archive, système).

Entrées
OctetsTypeRôle
P0-P1addradresse du nom (précédé de sa longueur)
P2uint8attributs, comme 3,16 : bit 1 système, 2 archive, 3 lecture seule, 4 caché
Sorties
OctetsTypeRôle
erreuruint8non nul si le fichier n'existe pas

Le bit « répertoire » (bit 0) ne peut pas être changé. L'exemple met le fichier en lecture seule (8) et relit ses attributs avec 3,16.

Texte de la documentation du firmware (anglais)

Sets the attributes for a file. On input:

Parameters:0,1 points to the length-prefixed filename; Parameter:2 is the attribute bitfield. (See Stat File for details.)

The directory bit cannot be changed. Obviously.

C (llvm-mos)
/* Mettre un fichier en lecture seule (groupe 3, fonction 21). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
    ControlPort.function = fonction;
    ControlPort.command = groupe;
    while (ControlPort.command)        /* attendre la fin */
        ;
}
static void libre(void) {              /* attendre que la boîte aux lettres soit libre */
    while (ControlPort.command)
        ;
}

static const uint8_t nom[] = "\x07" "abc.txt";

int main(void) {
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_set_attr("abc.txt", NEO_FILE_ATTR_READ_ONLY);  /* Set file attributes */
    libre();
    ControlPort.params[0] = (uint16_t)nom & 0xFF;
    ControlPort.params[1] = (uint16_t)nom >> 8;
    api(3, 16);                                 /* 3,16 : attributs en P4 */
    printf("Lecture seule : %u\n", ControlPort.params[4] & NEO_FILE_ATTR_READ_ONLY);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lecture seule : 8
Mad Pascal
// Mettre un fichier en lecture seule (groupe 3, fonction 21).
program attributs;
uses crt, neo6502;
var texte, nom: string[16];
    taille: cardinal;
    attr: byte;
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := 'abc.txt';
  attr := FI_ATTR_READONLY;
  NeoSetAttr(@nom, attr);                       // Set file attributes
  NeoStatFile(@nom, taille, attr);              // 3,16
  writeln('Lecture seule : ', attr and FI_ATTR_READONLY);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lecture seule : 8
NeoBASIC
10 ' Mettre un fichier en lecture seule (groupe 3, fonction 21)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 while peek($ff00) : wend
40 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff06, 8 : poke $ff01, 21 : poke $ff00, 3
50 while peek($ff00) : wend
60 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 16 : poke $ff00, 3
70 while peek($ff00) : wend : r = peek($ff08) & 8
80 print "Lecture seule : ";r
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lecture seule : 8
Assembleur 65C02 (64tass)
; Mettre un fichier en lecture seule (groupe 3, 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

start:
        jsr WaitMessage            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        jsr WaitMessage
        lda #<nom
        sta ControlPort+4          ; P0-P1 : nom
        lda #>nom
        sta ControlPort+5
        lda #8
        sta ControlPort+6          ; P2 : lecture seule
        lda #3
        ldx #21                    ; fonction 21 : Set file attributes
        jsr appel
        lda #<nom
        ldx #>nom
        ldy #16                    ; 3,16 : attributs en P4
        jsr sur_nom
        lda ControlPort+8
        and #8
        pha
        lda #<m
        ldx #>m
        jsr ecrire
        pla
        jsr decimal
        lda #13
        jmp WriteCharacter

; Appel du groupe 3, fonction Y, avec en P0-P1 l'adresse du nom donnée par A (poids faible) et X.
sur_nom:
        pha
        jsr WaitMessage
        pla
        sta ControlPort+4
        stx ControlPort+5
        tya
        tax
        lda #3
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

m:      .text "Lecture seule : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lecture seule : 8

3,22 Check End of File. Officiel

Indique si un canal ouvert est arrivé à la fin de son fichier.

Entrées
OctetsTypeRôle
P0uint8numéro du canal
Sorties
OctetsTypeRôle
P0uint8non nul en fin de fichier

Sur un canal fermé, l'appel peut signaler une erreur. En NeoBASIC, eof(n) fait le même appel.

Mots-clés NeoBASIC qui font cet appel : eof()

Texte de la documentation du firmware (anglais)

Returns the end of file status of an opened file. On input:

Parameter:0 contains the file channel to operate on.

On output: Parameter:0 is non-zero if the file is at the end of the file.

This call should be used on open files and may return an error if the file is closed.

C (llvm-mos)
/* Lire octet par octet jusqu'à la fin du fichier (groupe 3, fonction 22). */
#include <stdio.h>
#include <neo/api.h>

int main(void) {
    char c;
    unsigned n = 0;
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_open(1, "abc.txt", NEO_FILE_READ);
    while (!neo_file_eof(1)) {                  /* Check End of File */
        neo_file_read(1, &c, 1);
        n++;
    }
    neo_file_close(1);
    printf("%u octets lus avant la fin du fichier\n", n);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
8 octets lus avant la fin du fichier
Mad Pascal
// Lire octet par octet jusqu'à la fin du fichier (groupe 3, fonction 22).
program fin;
uses crt, neo6502;
var texte, nom: string[16];
    c: byte;
    n: word;

function fin_de_fichier(canal: byte): boolean;
begin
  NeoWaitMessage;
  NeoMessage.params[0] := canal;
  NeoSendMessage(3, 22);                        // Check End of File
  NeoWaitMessage;
  result := NeoMessage.params[0] <> 0;
end;

begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := 'abc.txt';
  NeoOpenFile(1, @nom, 0);
  n := 0;
  while not fin_de_fichier(1) do
  begin
    NeoReadFile(1, word(@c), 1);
    inc(n);
  end;
  NeoCloseFile(1);
  writeln(n, ' octets lus avant la fin du fichier');
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
8 octets lus avant la fin du fichier
NeoBASIC
10 ' Lire octet par octet jusqu'a la fin du fichier (groupe 3, fonction 22)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 b = alloc(4) : m = 0 : while peek($ff00) : wend : poke $ff04, 1 : poke $ff05, a & 255 : poke $ff06, a >> 8 : poke $ff07, m : poke $ff01, 4 : poke $ff00, 3 : while peek($ff00) : wend
40 n = 0
50 while eof(1) = 0
60 poke $ff04, 1 : poke $ff05, b & 255 : poke $ff06, b >> 8 : poke $ff07, 1 : poke $ff08, 0 : poke $ff01, 8 : poke $ff00, 3
70 while peek($ff00) : wend
80 n = n + 1
90 wend
100 close
110 print n;" octets lus avant la fin du fichier"
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
8 octets lus avant la fin du fichier
Assembleur 65C02 (64tass)
; Lire octet par octet jusqu'à la fin du fichier (groupe 3, fonction 22).
        .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            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        lda #0
        jsr ouvrir
_suiv:  jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #3
        ldx #22                    ; fonction 22 : Check End of File
        jsr appel
        lda ControlPort+4          ; non nul : fin
        bne _fin
        jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #<octet
        sta ControlPort+5
        lda #>octet
        sta ControlPort+6
        lda #1
        sta ControlPort+7
        stz ControlPort+8
        lda #3
        ldx #8                     ; lire un octet
        jsr appel
        inc compte
        bra _suiv
_fin:   jsr fermer
        lda compte
        jsr decimal
        lda #<m
        ldx #>m
        jmp ecrire
; Ouvrir abc.txt sur le canal 1 dans le mode A.
ouvrir: pha
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<nom
        sta ControlPort+5          ; P1-P2 : nom
        lda #>nom
        sta ControlPort+6
        pla
        sta ControlPort+7          ; P3 : mode
        lda #3
        ldx #4                     ; 3,4 : File Open
        jmp appel

; Fermer le canal 1.
fermer: jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #3
        ldx #5                     ; 3,5 : File Close
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

octet:  .byte 0
compte: .byte 0
m:      .text " octets lus avant la fin du fichier", 13, 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
8 octets lus avant la fin du fichier

3,23 Get Current Working Directory. Modifié par Trinity

Copie le chemin du répertoire courant dans un tampon.

Entrées
OctetsTypeRôle
P0-P1addradresse du tampon
P2uint8longueur maximale du chemin
Sorties
OctetsTypeRôle
tamponstringchemin (précédé de sa longueur)

Le chemin revient précédé de sa longueur, suivi d'un zéro sur Trinity (observé). neo_file_get_cwd de llvm-mos rend ce tampon tel quel : le premier octet est la longueur, le texte commence au second. L'exemple C en tient compte.

Différence dans Trinity — Trinity borne la copie à la longueur donnée en P2 (T-61).

Texte de la documentation du firmware (anglais)

Copies the current working directory into the String at address Parameters:0,1. which is of maximum length Parameters:2

C (llvm-mos)
/* Afficher le répertoire courant (groupe 3, fonction 23). */
#include <stdio.h>
#include <neo/api.h>

static char cwd[33];

static const char *courant(void) {
    neo_file_get_cwd(cwd, 32);                  /* 3,23 : chaîne précédée de sa longueur */
    cwd[(uint8_t)cwd[0] + 1] = 0;
    return cwd + 1;
}

int main(void) {
    printf("Repertoire courant : %s\n", courant());   /* Get Current Working Directory */
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Repertoire courant : /
Mad Pascal
// Afficher le répertoire courant (groupe 3, fonction 23).
program cwd;
uses crt, neo6502;

function courant: string;
var cwd: string[32];
begin
  NeoWaitMessage;
  wordParams[0] := word(@cwd);                  // P0-P1 : tampon
  NeoMessage.params[2] := 32;                   // P2 : longueur maximale
  NeoSendMessage(3, 23);                        // 3,23 : Get Current Working Directory
  NeoWaitMessage;
  result := cwd;
end;

begin
  writeln('Repertoire courant : ', courant);   // Get Current Working Directory
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Repertoire courant : /
NeoBASIC
10 ' Afficher le repertoire courant (groupe 3, fonction 23)
20 while peek($ff00) : wend
30 b = alloc(34) : poke $ff04, b & 255 : poke $ff05, b >> 8 : poke $ff06, 32 : poke $ff01, 23 : poke $ff00, 3
40 while peek($ff00) : wend : s$ = "" : for i = 1 to peek(b) : s$ = s$ + chr$(peek(b + i)) : next i
50 print "Repertoire courant : ";s$
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Repertoire courant : /
Assembleur 65C02 (64tass)
; Afficher le répertoire courant (groupe 3, 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 courant                ; fonction 23 : Get Current Working Directory
        lda #<m
        ldx #>m
        jsr ecrire
        lda #<cwd
        ldx #>cwd
        jsr pecrire
        lda #13
        jmp WriteCharacter

; Répertoire courant dans cwd (précédé de sa longueur).
courant:
        jsr WaitMessage
        lda #<cwd
        sta ControlPort+4          ; P0-P1 : tampon
        lda #>cwd
        sta ControlPort+5
        lda #32
        sta ControlPort+6          ; P2 : longueur maximale
        lda #3
        ldx #23                    ; 3,23 : Get Current Working Directory
        jmp appel
cwd:    .fill 34

; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
        sta ptr
        stx ptr+1
        lda (ptr)
        sta reste
        ldy #1
_p:     lda reste
        beq _pf
        lda (ptr),y
        jsr WriteCharacter
        iny
        dec reste
        bra _p
_pf:    rts
reste:  .byte 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 "Repertoire courant : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Repertoire courant : /

3,24 Volume Info Trinity

Donne le nom et l'état d'un volume de stockage (clé USB, carte SD, dossier de l'hôte).

Entrées
OctetsTypeRôle
P0uint8numéro du volume (0 à 3)
P1-P2addradresse du tampon du nom ; son premier octet donne sa capacité
Sorties
OctetsTypeRôle
tamponstringnom du volume (précédé de sa longueur)
P3uint8attributs : bit 0 présent, bit 1 lecture seule, bit 2 réseau
erreuruint8non nul (lecteur invalide) si aucun volume n'a ce numéro

Pour énumérer les volumes, appeler la fonction pour 0 à 3. Dans les chemins du groupe, le préfixe « n: » désigne le volume n (« 1:/jeux/tetris.neo »). Le nom dépend du support : l'exemple l'affiche tel quel (l'émulateur du banc a un seul volume).

Texte de la documentation du firmware (anglais)

Retrieves information about a storage volume (Trinity T-18, F-102 of the fork). On input:

Parameter:0 is the volume number (0-3); Parameters:1,2 points to a length-prefixed buffer for returning the volume name.

On output, the buffer contains the length-prefixed volume name (e.g. "USB1", "SD0", "HOST") and Parameter:3 contains the volume attributes: bit 0 present, bit 1 read only, bit 2 network.

An error (Invalid Drive) is flagged if no volume with that number is mounted. Volumes are addressed in any path of this group by the prefix "n:" (e.g. "1:/games/tetris.neo"); a path without prefix refers to the current volume. Enumerate volumes by calling this function for 0 to 3.

C (llvm-mos)
/* Énumérer les volumes présents (groupe 3, fonction 24, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
    ControlPort.function = fonction;
    ControlPort.command = groupe;
    while (ControlPort.command)        /* attendre la fin */
        ;
}
static void libre(void) {              /* attendre que la boîte aux lettres soit libre */
    while (ControlPort.command)
        ;
}

static uint8_t nom[17];

int main(void) {
    for (uint8_t v = 0; v < 4; v++) {
        libre();
        nom[0] = 15;                            /* capacité */
        ControlPort.params[0] = v;              /* P0 : volume */
        ControlPort.params[1] = (uint16_t)nom & 0xFF;
        ControlPort.params[2] = (uint16_t)nom >> 8;
        api(3, 24);                             /* Volume Info */
        if (ControlPort.error)                  /* pas de volume n° v */
            continue;
        nom[nom[0] + 1] = 0;
        printf("Volume %u : %s\n", v, (char *)nom + 1);
    }
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Volume 0 : HOST0
Mad Pascal
// Énumérer les volumes présents (groupe 3, fonction 24, Trinity).
program volumes;
uses crt, neo6502;
var nom: string[15];
    v: byte;
begin
  for v := 0 to 3 do
  begin
    nom[0] := chr(15);                          // capacité
    NeoWaitMessage;
    NeoMessage.params[0] := v;                  // P0 : volume
    wordxParams[0] := word(@nom);               // P1-P2 : tampon
    NeoSendMessage(3, 24);                      // Volume Info
    NeoWaitMessage;
    if NeoMessage.error = 0 then
      writeln('Volume ', v, ' : ', nom);
  end;
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Volume 0 : HOST0
NeoBASIC
10 ' Enumerer les volumes presents (groupe 3, fonction 24, Trinity)
20 b = alloc(18)
30 for v = 0 to 3
40 poke b, 15 : while peek($ff00) : wend
50 poke $ff04, v : poke $ff05, b & 255 : poke $ff06, b >> 8 : poke $ff01, 24 : poke $ff00, 3
60 while peek($ff00) : wend : e = peek($ff02)
70 if e = 0
80 s$ = "" : for i = 1 to peek(b) : s$ = s$ + chr$(peek(b + i)) : next i
90 print "Volume ";v;" : ";s$
100 endif
110 next v
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Volume 0 : HOST0
Assembleur 65C02 (64tass)
; Énumérer les volumes présents (groupe 3, fonction 24, Trinity).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  stz vol
_suiv:  lda #15
        sta vnom                   ; capacité
        jsr WaitMessage
        lda vol
        sta ControlPort+4          ; P0 : volume
        lda #<vnom
        sta ControlPort+5          ; P1-P2 : tampon
        lda #>vnom
        sta ControlPort+6
        lda #3
        ldx #24                    ; fonction 24 : Volume Info
        jsr appel
        lda ControlPort+2
        bne _autre                 ; pas de volume de ce numéro
        lda #<m
        ldx #>m
        jsr ecrire
        lda vol
        jsr decimal
        lda #<m2
        ldx #>m2
        jsr ecrire
        lda #<vnom
        ldx #>vnom
        jsr pecrire
        lda #13
        jsr WriteCharacter
_autre: inc vol
        lda vol
        cmp #4
        bne _suiv
        rts

; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
        sta ptr
        stx ptr+1
        lda (ptr)
        sta reste
        ldy #1
_p:     lda reste
        beq _pf
        lda (ptr),y
        jsr WriteCharacter
        iny
        dec reste
        bra _p
_pf:    rts
reste:  .byte 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

vol:    .byte 0
vnom:   .fill 17
m:      .text "Volume ", 0
m2:     .text " : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Volume 0 : HOST0

3,25 Select Volume Trinity

Fait d'un volume le volume courant : les chemins sans préfixe « n: » s'y rapportent ensuite.

Entrées
OctetsTypeRôle
P0uint8numéro du volume (0 à 3)
Sorties
OctetsTypeRôle
erreuruint8non nul si le volume n'est pas monté

Chaque volume garde son propre répertoire courant. L'exemple choisit le volume 0, le seul présent dans l'émulateur du banc, et le relit avec 3,26.

Texte de la documentation du firmware (anglais)

Makes a volume the current one (Trinity T-18, F-102 of the fork), like Function 3,15 "Change Directory" for directories: paths without a "n:" prefix then refer to it. On input:

Parameter:0 is the volume number (0-3).

An error is flagged if the volume is not mounted. Each volume keeps its own current directory.

C (llvm-mos)
/* Choisir le volume 0 (groupe 3, fonction 25, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
    ControlPort.function = fonction;
    ControlPort.command = groupe;
    while (ControlPort.command)        /* attendre la fin */
        ;
}
static void libre(void) {              /* attendre que la boîte aux lettres soit libre */
    while (ControlPort.command)
        ;
}

static uint8_t volume_courant(void) {
    libre();
    api(3, 26);                                 /* 3,26 : Get Current Volume */
    return ControlPort.params[0];
}

int main(void) {
    libre();
    ControlPort.params[0] = 0;                  /* P0 : volume */
    api(3, 25);                                 /* Select Volume */
    uint8_t e = ControlPort.error;
    printf("Volume 0 choisi, erreur %u, volume courant : %u\n", e, volume_courant());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Volume 0 choisi, erreur 0, volume courant : 0
Mad Pascal
// Choisir le volume 0 (groupe 3, fonction 25, Trinity).
program choisir;
uses crt, neo6502;
var e, v: byte;
begin
  NeoWaitMessage;
  NeoMessage.params[0] := 0;                    // P0 : volume
  NeoSendMessage(3, 25);                        // Select Volume
  NeoWaitMessage;
  e := NeoMessage.error;
  NeoSendMessage(3, 26);                        // 3,26 : Get Current Volume
  NeoWaitMessage;
  v := NeoMessage.params[0];
  writeln('Volume 0 choisi, erreur ', e, ', volume courant : ', v);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Volume 0 choisi, erreur 0, volume courant : 0
NeoBASIC
10 ' Choisir le volume 0 (groupe 3, fonction 25, Trinity)
20 while peek($ff00) : wend
30 poke $ff04, 0 : poke $ff01, 25 : poke $ff00, 3
40 while peek($ff00) : wend : e = peek($ff02)
50 poke $ff01, 26 : poke $ff00, 3
60 while peek($ff00) : wend : v = peek($ff04)
70 print "Volume 0 choisi, erreur ";e;", volume courant : ";v
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Volume 0 choisi, erreur 0, volume courant : 0
Assembleur 65C02 (64tass)
; Choisir le volume 0 (groupe 3, fonction 25, Trinity).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  jsr WaitMessage
        stz ControlPort+4          ; P0 : volume 0
        lda #3
        ldx #25                    ; fonction 25 : Select Volume
        jsr appel
        lda ControlPort+2
        sta err
        lda #3
        ldx #26                    ; 3,26 : Get Current Volume
        jsr appel
        lda ControlPort+4
        sta vol
        lda #<m1
        ldx #>m1
        jsr ecrire
        lda err
        jsr decimal
        lda #<m2
        ldx #>m2
        jsr ecrire
        lda vol
        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

err:    .byte 0
vol:    .byte 0
m1:     .text "Volume 0 choisi, erreur ", 0
m2:     .text ", volume courant : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Volume 0 choisi, erreur 0, volume courant : 0

3,26 Get Current Volume Trinity

Donne le numéro du volume courant.

Entrées : aucune.

Sorties
OctetsTypeRôle
P0uint8numéro du volume courant (0 à 3)
Texte de la documentation du firmware (anglais)

Returns the current volume number in Parameter:0 (Trinity T-18, F-102 of the fork).

C (llvm-mos)
/* Numéro du volume courant (groupe 3, fonction 26, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
    ControlPort.function = fonction;
    ControlPort.command = groupe;
    while (ControlPort.command)        /* attendre la fin */
        ;
}
static void libre(void) {              /* attendre que la boîte aux lettres soit libre */
    while (ControlPort.command)
        ;
}

int main(void) {
    libre();
    api(3, 26);                                 /* Get Current Volume */
    printf("Volume courant : %u\n", ControlPort.params[0]);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Volume courant : 0
Mad Pascal
// Numéro du volume courant (groupe 3, fonction 26, Trinity).
program volume;
uses crt, neo6502;
var v: byte;
begin
  NeoWaitMessage;
  NeoSendMessage(3, 26);                        // Get Current Volume
  NeoWaitMessage;
  v := NeoMessage.params[0];
  writeln('Volume courant : ', v);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Volume courant : 0
NeoBASIC
10 ' Numero du volume courant (groupe 3, fonction 26, Trinity)
20 while peek($ff00) : wend
30 poke $ff01, 26 : poke $ff00, 3
40 while peek($ff00) : wend : v = peek($ff04)
50 print "Volume courant : ";v
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Volume courant : 0
Assembleur 65C02 (64tass)
; Numéro du volume courant (groupe 3, fonction 26, Trinity).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  jsr WaitMessage
        lda #3
        ldx #26                    ; fonction 26 : Get Current Volume
        jsr appel
        lda ControlPort+4          ; P0 : volume
        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 "Volume courant : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Volume courant : 0

3,27 File Read Paged Trinity

Lit un fichier ouvert directement dans une page de mémoire adressée par le blitter (mémoire du 6502, vidéo ou graphique), sans passer par la mémoire du 6502.

Entrées
OctetsTypeRôle
P0uint8numéro du canal
P1uint8page : $00 mémoire du 6502, $80 et $81 mémoire vidéo, $90 mémoire graphique (comme 12,2)
P2-P3addradresse dans la page
P4-P5uint16nombre d'octets demandés
Sorties
OctetsTypeRôle
P4-P5uint16nombre d'octets réellement lus

La plage doit tenir dans la page (sinon : paramètre invalide) ; pas de passage de $80 à $81 en un appel. Les pages de banques $A0-$BF sont refusées. Une image 320×240 se lit en 65536 octets en page $80 puis 11264 en page $81. L'exemple lit en page $00 pour pouvoir afficher le résultat.

Texte de la documentation du firmware (anglais)

Reads data from an opened file directly into any memory the blitter can address (Trinity T-18, F-16 of the fork), avoiding a copy through 6502 RAM and Function 12,2. On input:

Parameter:0 contains the file channel to operate on. Parameter:1 is the memory page : $00 6502 RAM, $80 and $81 video RAM (line 205 onwards is in page $81), $90 graphics RAM — the same pages as Function 12,2. The bank pages $A0-$BF are refused (Invalid Parameter) : banks live in flash and are written by Function 1,22 only. Parameters:2,3 is the 16 bit address within that page. Parameters:4,5 contains the amount of data to read.

On output Parameters:4,5 is updated to contain the amount of data actually read. Data is read from the current seek position, which is advanced after the read.

The whole range must fit in the page : an Invalid Parameter error is flagged if it does not (no wrap-around, no crossing from $80 to $81 : use two calls). A full 320x240 frame is read with 65536 bytes into page $80 then 11264 bytes into page $81.

C (llvm-mos)
/* Lire un fichier par 3,27 en page $00 (groupe 3, fonction 27, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
    ControlPort.function = fonction;
    ControlPort.command = groupe;
    while (ControlPort.command)        /* attendre la fin */
        ;
}
static void libre(void) {              /* attendre que la boîte aux lettres soit libre */
    while (ControlPort.command)
        ;
}

static char tampon[9];

int main(void) {
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_open(1, "abc.txt", NEO_FILE_READ);
    libre();
    ControlPort.params[0] = 1;                  /* P0 : canal */
    ControlPort.params[1] = 0x00;               /* P1 : page $00, mémoire du 6502 */
    ControlPort.params[2] = (uint16_t)tampon & 0xFF;   /* P2-P3 : adresse */
    ControlPort.params[3] = (uint16_t)tampon >> 8;
    ControlPort.params[4] = 8;                  /* P4-P5 : 8 octets */
    ControlPort.params[5] = 0;
    api(3, 27);                                 /* File Read Paged */
    uint8_t n = ControlPort.params[4];
    neo_file_close(1);
    printf("Lu par 3,27 : %s (%u octets)\n", tampon, n);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lu par 3,27 : ABCDEFGH (8 octets)
Mad Pascal
// Lire un fichier par 3,27 en page $00 (groupe 3, fonction 27, Trinity).
program pagine;
uses crt, neo6502;
var texte, nom, tampon: string[16];
    n: byte;
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := 'abc.txt';
  NeoOpenFile(1, @nom, 0);
  NeoWaitMessage;
  NeoMessage.params[0] := 1;                    // P0 : canal
  NeoMessage.params[1] := $00;                  // P1 : page $00, mémoire du 6502
  wordParams[1] := word(@tampon) + 1;           // P2-P3 : adresse
  wordParams[2] := 8;                           // P4-P5 : 8 octets
  NeoSendMessage(3, 27);                        // File Read Paged
  NeoWaitMessage;
  n := NeoMessage.params[4];
  NeoCloseFile(1);
  tampon[0] := chr(n);
  writeln('Lu par 3,27 : ', tampon, ' (', n, ' octets)');
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lu par 3,27 : ABCDEFGH (8 octets)
NeoBASIC
10 ' Lire un fichier par 3,27 en page $00 (groupe 3, fonction 27, Trinity)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 b = alloc(16) : while peek($ff00) : wend
40 poke $ff04, 1 : poke $ff05, a & 255 : poke $ff06, a >> 8 : poke $ff07, 0 : poke $ff01, 4 : poke $ff00, 3
50 while peek($ff00) : wend
60 poke $ff04, 1 : poke $ff05, 0 : poke $ff06, b & 255 : poke $ff07, b >> 8 : poke $ff08, 8 : poke $ff09, 0 : poke $ff01, 27 : poke $ff00, 3
70 while peek($ff00) : wend : n = peek($ff08)
80 close
90 s$ = "" : for i = 0 to n - 1 : s$ = s$ + chr$(peek(b + i)) : next i
100 print "Lu par 3,27 : ";s$;" (";n;" octets)"
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lu par 3,27 : ABCDEFGH (8 octets)
Assembleur 65C02 (64tass)
; Lire un fichier par 3,27 en page $00 (groupe 3, fonction 27, Trinity).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:
        jsr WaitMessage            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<nom
        sta ControlPort+5
        lda #>nom
        sta ControlPort+6
        stz ControlPort+7          ; lecture seule
        lda #3
        ldx #4                     ; 3,4 : File Open
        jsr appel
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        stz ControlPort+5          ; P1 : page $00, mémoire du 6502
        lda #<tampon
        sta ControlPort+6          ; P2-P3 : adresse
        lda #>tampon
        sta ControlPort+7
        lda #8
        sta ControlPort+8          ; P4-P5 : 8 octets
        stz ControlPort+9
        lda #3
        ldx #27                    ; fonction 27 : File Read Paged
        jsr appel
        lda ControlPort+8
        sta lus
        jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #3
        ldx #5                     ; 3,5 : File Close
        jsr appel
        lda #<m1
        ldx #>m1
        jsr ecrire
        lda #<tampon
        ldx #>tampon
        jsr ecrire
        lda #<m2
        ldx #>m2
        jsr ecrire
        lda lus
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

tampon: .fill 9                    ; zéros : la chaîne lue sera terminée
lus:    .byte 0
m1:     .text "Lu par 3,27 : ", 0
m2:     .text " (", 0
m3:     .text " octets)", 13, 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lu par 3,27 : ABCDEFGH (8 octets)

3,28 File Read Background Trinity

Lit un fichier ouvert comme 3,27, mais rend la main tout de suite : le 65C02 continue pendant la lecture, dont trois octets de la mémoire suivent l'avancement.

Entrées
OctetsTypeRôle
P0uint8numéro du canal
P1uint8page : $00 mémoire du 6502, $80 et $81 mémoire vidéo, $90 mémoire graphique (comme 3,27)
P2-P3addradresse dans la page
P4-P5uint16nombre d'octets demandés
P6-P7addradresse des 3 octets de suivi (mémoire du 6502)
Sorties
OctetsTypeRôle
suivi+0uint8$01 pendant la lecture, puis $80 + code d'erreur ($80 : réussi)
suivi+1-2uint16nombre d'octets lus
erreuruint8seulement si les octets de suivi sont dans la cible ou au-delà de $FF00 (rien n'est lu) ; tout autre problème passe par l'octet de suivi

Surveiller l'octet de suivi et ne toucher ni à lui ni à la cible avant son bit 7. Un appel de l'API fait entre-temps est accepté mais attend la fin de la lecture. Sur la carte, le 65C02 tourne pendant les transferts de la clé USB (environ 90 % du temps d'une lecture, mesuré) ; les émulateurs lisent tout de suite, d'où une lecture déjà finie au banc. L'exemple demande 16 octets d'un fichier de 8 (état 128, 8 octets lus), puis place le suivi dans la cible : refus, erreur 21 (paramètre invalide).

Texte de la documentation du firmware (anglais)

Function 3,27 without stopping the 65C02 (Trinity T-82, ADR-0002) : Parameters:0 to 5 as Function 3,27 (channel, page, address, size), Parameters:6,7 the address of 3 bytes of 6502 RAM that report the read. The call returns at once with the first byte at $01 ; the program runs on while the firmware reads, and when the read is over the first byte becomes $80 plus the error code ($80 = success, $82 = end of file...) and the next two bytes hold the number of bytes read. Poll the first byte in RAM ; do not touch it, nor the destination, before its bit 7 is set. Any API call made meanwhile is accepted but waits until the read is over. The error flag is set only when the state bytes are inside the destination or past $FF00 (nothing is read then) ; every other outcome, bad parameters included, is reported by the state byte alone, the same on the board and in the emulators. On the board the 65C02 runs while the USB key transfers (about 90% of the time of a read, measured) ; the emulators perform the read at once.

C (llvm-mos)
/* Lire un fichier sans arrêter le 65C02 (groupe 3, fonction 28, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
    ControlPort.function = fonction;
    ControlPort.command = groupe;
    while (ControlPort.command)        /* attendre la fin */
        ;
}
static void libre(void) {              /* attendre que la boîte aux lettres soit libre */
    while (ControlPort.command)
        ;
}

static char tampon[17];
static volatile uint8_t etat[3];                /* état, puis nombre d'octets lus (écrits par le firmware) */

static uint8_t lire(uint16_t cible, uint16_t suivi) {   /* 3,28 : 16 octets du canal 1 en cible ; erreur rendue */
    libre();
    ControlPort.params[0] = 1;                  /* P0 : canal */
    ControlPort.params[1] = 0x00;               /* P1 : page $00, mémoire du 6502 */
    ControlPort.params[2] = cible & 0xFF;       /* P2-P3 : adresse */
    ControlPort.params[3] = cible >> 8;
    ControlPort.params[4] = 16;                 /* P4-P5 : 16 octets demandés */
    ControlPort.params[5] = 0;
    ControlPort.params[6] = suivi & 0xFF;       /* P6-P7 : les 3 octets d'état */
    ControlPort.params[7] = suivi >> 8;
    api(3, 28);                                 /* File Read Background : rend la main tout de suite */
    return ControlPort.error;
}

int main(void) {
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_open(1, "abc.txt", NEO_FILE_READ);
    lire((uint16_t)tampon, (uint16_t)etat);
    uint16_t tours = 0;
    while (!(etat[0] & 0x80))                   /* le programme continue pendant la lecture */
        tours++;
    printf("Lu : %s, etat %u, %u octets\n", tampon, etat[0], etat[1] | etat[2] << 8);
    printf("Suivi dans la cible : erreur %u\n", lire((uint16_t)tampon, (uint16_t)tampon + 4));
    neo_file_close(1);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lu : ABCDEFGH, etat 128, 8 octets
Suivi dans la cible : erreur 21
Mad Pascal
// Lire un fichier sans arrêter le 65C02 (groupe 3, fonction 28, Trinity).
program fond;
uses crt, neo6502;
var texte, nom, tampon: string[16];
    etat: array[0..2] of byte;                  // état, puis nombre d'octets lus (écrits par le firmware)
    e: byte;
    tours: word;

function lire(cible, suivi: word): byte;        // 3,28 : 16 octets du canal 1 en cible ; erreur rendue
begin
  NeoWaitMessage;
  NeoMessage.params[0] := 1;                    // P0 : canal
  NeoMessage.params[1] := $00;                  // P1 : page $00, mémoire du 6502
  wordParams[1] := cible;                       // P2-P3 : adresse
  wordParams[2] := 16;                          // P4-P5 : 16 octets demandés
  wordParams[3] := suivi;                       // P6-P7 : les 3 octets d'état
  NeoSendMessage(3, 28);                        // File Read Background : rend la main tout de suite
  NeoWaitMessage;
  result := NeoMessage.error;
end;

begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := 'abc.txt';
  NeoOpenFile(1, @nom, 0);
  lire(word(@tampon) + 1, word(@etat));
  tours := 0;
  while etat[0] and $80 = 0 do inc(tours);      // le programme continue pendant la lecture
  tampon[0] := chr(etat[1]);
  writeln('Lu : ', tampon, ', etat ', etat[0], ', ', etat[1] + etat[2] shl 8, ' octets');
  e := lire(word(@tampon) + 1, word(@tampon) + 5);
  writeln('Suivi dans la cible : erreur ', e);
  NeoCloseFile(1);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lu : ABCDEFGH, etat 128, 8 octets
Suivi dans la cible : erreur 21
NeoBASIC
10 ' Lire un fichier sans arreter le 65C02 (groupe 3, fonction 28, Trinity)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 b = alloc(16) : s = alloc(3) : while peek($ff00) : wend
40 poke $ff04, 1 : poke $ff05, a & 255 : poke $ff06, a >> 8 : poke $ff07, 0 : poke $ff01, 4 : poke $ff00, 3
50 c = b : gosub 1000 : ' lecture, suivi en s
60 repeat : until peek(s) & $80 : ' le programme continue pendant la lecture
70 e = peek(s) : n = peek(s + 1) : ' etat, octets lus
80 s$ = "" : for i = 0 to n - 1 : s$ = s$ + chr$(peek(b + i)) : next i
90 print "Lu : ";s$;", etat ";e;", ";n;" octets"
100 s = b + 4 : gosub 1000 : print "Suivi dans la cible : erreur ";r
110 close
120 end
1000 ' 3,28 : 16 octets du canal 1 en c, 3 octets d'etat en s ; erreur dans r
1010 while peek($ff00) : wend
1020 poke $ff04, 1 : poke $ff05, 0 : doke $ff06, c : doke $ff08, 16 : doke $ff0a, s
1030 poke $ff01, 28 : poke $ff00, 3 : ' File Read Background : rend la main tout de suite
1040 while peek($ff00) : wend : r = peek($ff02)
1050 return
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lu : ABCDEFGH, etat 128, 8 octets
Suivi dans la cible : erreur 21
Assembleur 65C02 (64tass)
; Lire un fichier sans arrêter le 65C02 (groupe 3, fonction 28, Trinity).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:
        jsr WaitMessage            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        jsr WaitMessage
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        lda #<nom
        sta ControlPort+5
        lda #>nom
        sta ControlPort+6
        stz ControlPort+7          ; lecture seule
        lda #3
        ldx #4                     ; 3,4 : File Open
        jsr appel
        lda #<etat                 ; suivi hors de la cible
        ldx #>etat
        jsr lire
_att:   bit etat                   ; le programme continue pendant la lecture...
        bpl _att                   ; ... jusqu'au bit 7 de l'état
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda #<tampon
        ldx #>tampon
        jsr ecrire                 ; la cible est à zéro au-delà des 8 octets lus
        lda #<t1
        ldx #>t1
        jsr ecrire
        lda etat
        jsr decimal
        lda #<t2
        ldx #>t2
        jsr ecrire
        lda etat+1                 ; octets lus (poids faible)
        jsr decimal
        lda #<t3
        ldx #>t3
        jsr ecrire
        lda #<(tampon+4)           ; suivi dans la cible : refusé
        ldx #>(tampon+4)
        jsr lire
        lda ControlPort+2
        sta err
        lda #<t4
        ldx #>t4
        jsr ecrire
        lda err
        jsr decimal
        lda #13
        jsr WriteCharacter
        jsr WaitMessage
        lda #1
        sta ControlPort+4
        lda #3
        ldx #5                     ; 3,5 : File Close
        jmp appel

; 3,28 : 16 octets du canal 1 dans tampon, les 3 octets d'état à l'adresse A (poids faible), X (poids fort).
lire:   pha
        jsr WaitMessage
        pla
        sta ControlPort+10         ; P6-P7 : les 3 octets d'état
        stx ControlPort+11
        lda #1
        sta ControlPort+4          ; P0 : canal 1
        stz ControlPort+5          ; P1 : page $00, mémoire du 6502
        lda #<tampon
        sta ControlPort+6          ; P2-P3 : adresse
        lda #>tampon
        sta ControlPort+7
        lda #16
        sta ControlPort+8          ; P4-P5 : 16 octets demandés
        stz ControlPort+9
        lda #3
        ldx #28                    ; 3,28 : File Read Background, rend la main tout de suite
        jmp appel

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"
tampon: .fill 17                   ; zéros : la chaîne lue sera terminée
etat:   .fill 3                    ; état, puis nombre d'octets lus (écrits par le firmware)
err:    .byte 0
t0:     .text "Lu : ", 0
t1:     .text ", etat ", 0
t2:     .text ", ", 0
t3:     .text " octets", 13, 0
t4:     .text "Suivi dans la cible : erreur ", 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
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Lu : ABCDEFGH, etat 128, 8 octets
Suivi dans la cible : erreur 21

3,29 Last Entry Date Time Trinity

Donne la date et l'heure de la dernière entrée lue par 3,16 (File Stat) ou 3,18 (Read Directory), au format FAT.

Entrées : aucune.

Sorties
OctetsTypeRôle
P0-P1uint16date : bits 15-9 année - 1980, 8-5 mois, 4-0 jour ; 0 si inconnue
P2-P3uint16heure : bits 15-11 heure, 10-5 minutes, 4-0 secondes / 2 ; 0 si inconnue
erreuruint81 si aucune entrée n'a encore été lue

P0-P3 sont écrits dans tous les cas, erreur comprise : NeoDOS s'en sert pour distinguer ce firmware d'un plus ancien, qui les laisse tels quels (c'est ainsi que DIR affiche les dates). Dans les émulateurs, la date est celle de la modification du fichier sur l'ordinateur hôte, en heure locale : la sortie observée est donc la date du passage au banc, et le motif vérifié ne porte que sur le format. Les secondes sont paires (précision FAT de 2 s).

Texte de la documentation du firmware (anglais)

Returns the date and time of the last entry read by Function 3,16 File Stat or 3,18 Read Directory, in the FAT format (Trinity T-91) : Parameters:0,1 the date (bits 15-9 year - 1980, 8-5 month, 4-0 day), Parameters:2,3 the time (bits 15-11 hour, 10-5 minutes, 4-0 seconds / 2) ; both 0 when the date is unknown. Sets the error flag if no entry has been read yet. Parameters:0-3 are written in every case, error included (NeoDOS relies on it to tell this function from an older firmware that leaves them untouched). On the emulators the date is the host file's modification time, in local time.

C (llvm-mos)
/* Lire la date d'un fichier (groupe 3, fonction 29, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>

/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
    ControlPort.function = fonction;
    ControlPort.command = groupe;
    while (ControlPort.command)        /* attendre la fin */
        ;
}
static void libre(void) {              /* attendre que la boîte aux lettres soit libre */
    while (ControlPort.command)
        ;
}

static const uint8_t nom[] = "\x07" "abc.txt";   /* chaîne à longueur */

int main(void) {
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    libre();
    ControlPort.params[0] = (uint16_t)nom & 0xFF;   /* P0-P1 : nom */
    ControlPort.params[1] = (uint16_t)nom >> 8;
    api(3, 16);                                 /* File Stat : l'entrée dont on veut la date */
    api(3, 29);                                 /* Last Entry Date Time */
    uint16_t d = ControlPort.params[0] | ControlPort.params[1] << 8;   /* date FAT */
    uint16_t h = ControlPort.params[2] | ControlPort.params[3] << 8;   /* heure FAT */
    printf("abc.txt : %u-%02u-%02u %02u:%02u:%02u\n",
           1980 + (d >> 9), (d >> 5) & 15, d & 31,  /* année - 1980, mois, jour */
           h >> 11, (h >> 5) & 63, (h & 31) * 2);   /* heure, minutes, secondes / 2 */
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt : 2026-10-03 15:19:38
Mad Pascal
// Lire la date d'un fichier (groupe 3, fonction 29, Trinity).
program datefichier;
uses crt, neo6502;
var texte, nom: string[16];
    taille: cardinal;
    attr: byte;
    d, h: word;

procedure deux(n: word);                        // deux chiffres
begin
  if n < 10 then write('0');
  write(n);
end;

begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  nom := 'abc.txt';
  NeoStatFile(@nom, taille, attr);              // 3,16 : l'entrée dont on veut la date
  NeoSendMessage(3, 29);                        // Last Entry Date Time
  NeoWaitMessage;
  d := wordParams[0];                           // date FAT
  h := wordParams[1];                           // heure FAT
  write('abc.txt : ', 1980 + d shr 9, '-');     // année - 1980
  deux((d shr 5) and 15); write('-');           // mois
  deux(d and 31); write(' ');                   // jour
  deux(h shr 11); write(':');                   // heure
  deux((h shr 5) and 63); write(':');           // minutes
  deux((h and 31) * 2);                         // secondes / 2
  writeln;
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt : 2026-10-03 15:19:36
NeoBASIC
10 ' Lire la date d'un fichier (groupe 3, fonction 29, Trinity)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 while peek($ff00) : wend
40 poke $ff04, a & 255 : poke $ff05, a >> 8 : poke $ff01, 16 : poke $ff00, 3 : ' 3,16 : l'entree dont on veut la date
50 while peek($ff00) : wend
60 poke $ff01, 29 : poke $ff00, 3 : ' Last Entry Date Time
70 while peek($ff00) : wend : d = deek($ff04) : h = deek($ff06) : ' date et heure FAT, lues avant tout calcul
80 print "abc.txt : ";1980 + (d >> 9);"-";
90 n = (d >> 5) & 15 : gosub 1000 : print "-"; : n = d & 31 : gosub 1000 : print " ";
100 n = h >> 11 : gosub 1000 : print ":"; : n = (h >> 5) & 63 : gosub 1000 : print ":"; : n = (h & 31) * 2 : gosub 1000
110 print
120 end
1000 ' n sur deux chiffres
1010 if n < 10 then print "0";
1020 print n;
1030 return
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt : 2026-10-03 15:19:38
Assembleur 65C02 (64tass)
; Lire la date d'un fichier (groupe 3, fonction 29, Trinity).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:
        jsr WaitMessage            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        jsr WaitMessage
        lda #<nom
        sta ControlPort+4          ; P0-P1 : nom
        lda #>nom
        sta ControlPort+5
        lda #3
        ldx #16                    ; 3,16 : File Stat, l'entrée dont on veut la date
        jsr appel
        lda #3
        ldx #29                    ; 3,29 : Last Entry Date Time
        jsr appel
        ldx #3                     ; copier date et heure avant tout affichage
_cp:    lda ControlPort+4,x
        sta date,x
        dex
        bpl _cp
        lda #<t0
        ldx #>t0
        jsr ecrire
        lda date+1                 ; année - 1980 : bits 15-9
        lsr a
        clc
        adc #80                    ; 1980 + a = 1900 + (a + 80)
        cmp #100
        bcs _2000
        pha
        lda #19
        bra _siecle
_2000:  sbc #100
        pha
        lda #20
_siecle:
        jsr deux
        pla
        jsr deux
        lda #'-'
        jsr WriteCharacter
        lda date+1                 ; mois : bits 8-5
        lsr a
        lda date
        ror a
        lsr a
        lsr a
        lsr a
        lsr a
        jsr deux
        lda #'-'
        jsr WriteCharacter
        lda date                   ; jour : bits 4-0
        and #31
        jsr deux
        lda #' '
        jsr WriteCharacter
        lda heure+1                ; heure : bits 15-11
        lsr a
        lsr a
        lsr a
        jsr deux
        lda #':'
        jsr WriteCharacter
        lda heure+1                ; minutes : bits 10-5
        and #7
        sta tmp
        lda heure
        lsr tmp
        ror a
        lsr tmp
        ror a
        lsr tmp
        ror a
        lsr a
        lsr a
        jsr deux
        lda #':'
        jsr WriteCharacter
        lda heure                  ; secondes / 2 : bits 4-0
        and #31
        asl a
        jsr deux
        lda #13
        jmp WriteCharacter

; Affiche A (0-99) sur deux chiffres.
deux:   cmp #10
        bcs _d
        pha
        lda #'0'
        jsr WriteCharacter
        pla
_d:     jmp decimal

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"
date:   .word 0                    ; date FAT
heure:  .word 0                    ; heure FAT
tmp:    .byte 0
t0:     .text "abc.txt : ", 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
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt : 2026-10-03 15:19:36

3,32 List Filtered Officiel

Affiche la liste des fichiers du répertoire courant dont le nom contient un texte donné.

Entrées
OctetsTypeRôle
P0-P1addradresse du texte cherché (précédé de sa longueur)

Sorties : aucune.

Recherche d'une sous-chaîne, pas de jokers. En NeoBASIC, cat "texte" fait le même appel (cat seul fait 3,1).

Texte de la documentation du firmware (anglais)

Prints a filtered file listing of the current directory to the console. On input:

Parameters:0,1 points to the filename search string.

Files will only be shown if the name contains the search string (ie: a substring match).

C (llvm-mos)
/* Lister les fichiers dont le nom contient « abc » (groupe 3, fonction 32). */
#include <neo/api.h>

int main(void) {
    neo_file_store("abc.txt", "ABCDEFGH", 8);  /* 3,3 : le fichier de l'exemple */
    neo_file_store("xyz.txt", "XYZ", 3);        /* un fichier qui ne sera pas listé */
    neo_file_list_filtered("abc");              /* List Filtered */
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt                         8 bytes.
Mad Pascal
// Lister les fichiers dont le nom contient « abc » (groupe 3, fonction 32).
program filtre;
uses crt, neo6502;
var texte, filtre: string[16];
begin
  texte := 'ABCDEFGH';
  NeoSave('abc.txt', word(@texte) + 1, 8);      // 3,3 : le fichier de l'exemple
  NeoSave('xyz.txt', word(@texte) + 1, 3);      // un fichier qui ne sera pas listé
  filtre := 'abc';
  NeoSearchDir(filtre);                         // List Filtered
  NeoWaitMessage;
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt                         8 bytes.
NeoBASIC
10 ' Lister les fichiers dont le nom contient abc (groupe 3, fonction 32)
20 d = alloc(16) : for i = 1 to 8 : poke d + i - 1, 64 + i : next i : save "abc.txt", d, 8 : ' le fichier : ABCDEFGH
25 n$ = "abc.txt" : a = alloc(16) : poke a, len(n$) : for i = 1 to len(n$) : poke a + i, asc(mid$(n$, i, 1)) : next i
30 save "xyz.txt", d, 3 : ' un fichier qui ne sera pas liste
40 cat "abc"
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt                         8 bytes.
Assembleur 65C02 (64tass)
; Lister les fichiers dont le nom contient « abc » (groupe 3, fonction 32).
        .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            ; 3,3 : le fichier de l'exemple, ABCDEFGH
        lda #<nom
        sta ControlPort+4
        lda #>nom
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #8
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        jsr WaitMessage            ; un fichier qui ne sera pas listé
        lda #<xyz
        sta ControlPort+4
        lda #>xyz
        sta ControlPort+5
        lda #<abc
        sta ControlPort+6
        lda #>abc
        sta ControlPort+7
        lda #3
        sta ControlPort+8
        stz ControlPort+9
        lda #3
        ldx #3
        jsr appel
        lda #<filtre
        ldx #>filtre
        ldy #32                    ; fonction 32 : List Filtered
        jmp sur_nom

; Appel du groupe 3, fonction Y, avec en P0-P1 l'adresse du nom donnée par A (poids faible) et X.
sur_nom:
        pha
        jsr WaitMessage
        pla
        sta ControlPort+4
        stx ControlPort+5
        tya
        tax
        lda #3
        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

nom:    .byte 7
        .text "abc.txt"
abc:    .text "ABCDEFGH"

xyz:    .byte 7
        .text "xyz.txt"
filtre: .byte 3
        .text "abc"
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abc.txt                         8 bytes.

← L'API du Neo6502