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;
}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.PROG.NEO 132 bytes.NeoBASIC
10 ' Lister le repertoire courant (groupe 3, fonction 1)
20 catprog.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 0PROG.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).
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du nom de fichier (précédé de sa longueur) |
P2-P3 | addr | adresse de destination, ou $FFFF pour la mémoire graphique |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | 0 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;
}Charge : BonjourMad 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.Charge : BonjourNeoBASIC
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 ";eCharge : BonjourAssembleur 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 : ", 0Charge : Bonjour3,3 Store File Officiel
Enregistre une zone de mémoire dans un fichier (créé ou remplacé).
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du nom de fichier (précédé de sa longueur) |
P2-P3 | addr | adresse des données |
P4-P5 | uint16 | nombre d'octets |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | 0 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;
}salut.txt : 7 octetsMad 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.salut.txt : 7 octetsNeoBASIC
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"salut.txt : 7 octetsAssembleur 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, 0salut.txt : 7 octets3,4 File Open Officiel
Ouvre un fichier sur un canal, en lecture, en écriture, ou les deux.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du canal |
P1-P2 | addr | adresse du nom (précédé de sa longueur) |
P3 | uint8 | mode : 0 lecture seule, 1 écriture seule, 2 lecture-écriture, 3 créer (ou vider) puis lecture-écriture |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | non 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;
}Ecrit : 7 octetsMad 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.Ecrit : 7 octetsNeoBASIC
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"Ecrit : 7 octetsAssembleur 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, 0Ecrit : 7 octets3,5 File Close Officiel
Ferme un canal ; $FF ferme tous les canaux ouverts.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numé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;
}Canal 1 ferme, erreur 0Mad 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.Canal 1 ferme, erreur 0NeoBASIC
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 ";eCanal 1 ferme, erreur 0Assembleur 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 ", 0Canal 1 ferme, erreur 03,6 File Seek Officiel
Place la position de lecture et d'écriture d'un canal à l'octet voulu.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du canal |
P1-P4 | uint32 | position (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;
}Octet a la position 4 : EMad 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.Octet a la position 4 : ENeoBASIC
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))Octet a la position 4 : EAssembleur 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 : ", 0Octet a la position 4 : E3,7 File Tell Officiel
Donne la position de lecture et d'écriture d'un canal.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du canal |
| Octets | Type | Rôle |
|---|---|---|
P1-P4 | uint32 | position |
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;
}Position apres 3 octets lus : 3Mad 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.Position apres 3 octets lus : 3NeoBASIC
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 : ";pPosition apres 3 octets lus : 3Assembleur 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 : ", 0Position apres 3 octets lus : 33,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).
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du canal |
P1-P2 | addr | destination, ou $FFFF pour la mémoire graphique |
P3-P4 | uint16 | nombre d'octets demandés |
| Octets | Type | Rôle |
|---|---|---|
P3-P4 | uint16 | nombre 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;
}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.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)"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, 0Lu : 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.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du canal |
P1-P2 | addr | adresse des données |
P3-P4 | uint16 | nombre d'octets |
| Octets | Type | Rôle |
|---|---|---|
P3-P4 | uint16 | nombre 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;
}Ecrits : 5, taille du fichier : 5Mad 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.Ecrits : 5, taille du fichier : 5NeoBASIC
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 : ";tEcrits : 5, taille du fichier : 5Assembleur 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 : ", 0Ecrits : 5, taille du fichier : 53,10 File Size Officiel
Donne la taille actuelle d'un fichier ouvert, écritures encore en tampon comprises.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du canal |
| Octets | Type | Rôle |
|---|---|---|
P1-P4 | uint32 | taille 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;
}Taille du fichier ouvert : 8Mad 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.Taille du fichier ouvert : 8NeoBASIC
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 : ";tTaille du fichier ouvert : 8Assembleur 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 : ", 0Taille du fichier ouvert : 83,11 File Set Size Officiel
Agrandit ou tronque un fichier ouvert à la taille voulue.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du canal |
P1-P4 | uint32 | nouvelle 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;
}Taille apres troncature : 3Mad 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.Taille apres troncature : 3NeoBASIC
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 : ";tTaille apres troncature : 3Assembleur 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 : ", 0Taille apres troncature : 33,12 File Rename Officiel
Renomme un fichier, éventuellement en le déplaçant dans un autre répertoire.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse de l'ancien nom (précédé de sa longueur) |
P2-P3 | addr | adresse du nouveau nom (précédé de sa longueur) |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | non 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;
}Renomme : abc.txt -> xyz.txt, erreur 0Mad 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.Renomme : abc.txt -> xyz.txt, erreur 0NeoBASIC
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 ";eRenomme : abc.txt -> xyz.txt, erreur 0Assembleur 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 ", 0Renomme : abc.txt -> xyz.txt, erreur 03,13 File Delete Officiel
Supprime un fichier, ou un répertoire vide.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du nom (précédé de sa longueur) |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | non 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;
}Supprime, puis 3,16 donne l'erreur 17Mad 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.Supprime, puis 3,16 donne l'erreur 17NeoBASIC
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 ";eSupprime, puis 3,16 donne l'erreur 17Assembleur 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 ", 0Supprime, puis 3,16 donne l'erreur 173,14 Create Directory Officiel
Crée un répertoire.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du nom (précédé de sa longueur) |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | non 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;
}Repertoire cree, bit repertoire : 1Mad 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.Repertoire cree, bit repertoire : 1NeoBASIC
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 : ";tRepertoire cree, bit repertoire : 1Assembleur 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 : ", 0Repertoire cree, bit repertoire : 13,15 Change Directory Officiel
Change le répertoire courant.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du chemin (précédé de sa longueur) |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | non 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;
}Repertoire courant : /repMad 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.Repertoire courant : /repNeoBASIC
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$Repertoire courant : /repAssembleur 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 : ", 0Repertoire courant : /rep3,16 File Stat Officiel
Donne la taille et les attributs d'un fichier, par son nom.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du nom (précédé de sa longueur) |
| Octets | Type | Rôle |
|---|---|---|
P0-P3 | uint32 | taille en octets |
P4 | uint8 | attributs : bit 0 répertoire, 1 système, 2 archive, 3 lecture seule, 4 caché |
erreur | uint8 | non 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;
}abc.txt : 8 octets, repertoire : 0Mad 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.abc.txt : 8 octets, repertoire : 0NeoBASIC
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 endifabc.txt : 8 octets, repertoire : 0Assembleur 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 : ", 0abc.txt : 8 octets, repertoire : 03,17 Open Directory Officiel
Ouvre un répertoire pour en lire les entrées une à une (3,18).
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du chemin (précédé de sa longueur) ; « . » pour le répertoire courant |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | non 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;
}abc.txt 8
PROG.NEO 4642Mad 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.abc.txt 8
PROG.NEO 741NeoBASIC
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) : wendabc.txt 8
prog.bas 925
boot 0Assembleur 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 34abc.txt 8
PROG.NEO 133,18 Read Directory Officiel
Lit l'entrée suivante du répertoire ouvert : nom, taille, attributs.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du tampon du nom ; son premier octet donne sa capacité |
| Octets | Type | Rôle |
|---|---|---|
tampon | string | nom (précédé de sa longueur), sans chemin |
P2-P5 | uint32 | taille en octets |
P6 | uint8 | attributs, comme 3,16 |
erreur | uint8 | non 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;
}abc.txt 8
PROG.NEO 4642Mad 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.abc.txt 8
PROG.NEO 741NeoBASIC
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) : wendabc.txt 8
prog.bas 925
boot 0Assembleur 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 34abc.txt 8
PROG.NEO 133,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;
}abc.txt 8
PROG.NEO 4642Mad 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.abc.txt 8
PROG.NEO 741NeoBASIC
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) : wendabc.txt 8
prog.bas 926
boot 0Assembleur 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 34abc.txt 8
PROG.NEO 133,20 Copy File Officiel
Copie un fichier sous un autre nom.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du nom d'origine (précédé de sa longueur) |
P2-P3 | addr | adresse du nom de la copie (précédé de sa longueur) |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | non 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;
}Copie : ABCDEFGHMad 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.Copie : ABCDEFGHNeoBASIC
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$Copie : ABCDEFGHAssembleur 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 : ", 0Copie : ABCDEFGH3,21 Set file attributes Officiel
Change les attributs d'un fichier (lecture seule, caché, archive, système).
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du nom (précédé de sa longueur) |
P2 | uint8 | attributs, comme 3,16 : bit 1 système, 2 archive, 3 lecture seule, 4 caché |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | non 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;
}Lecture seule : 8Mad 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.Lecture seule : 8NeoBASIC
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 : ";rLecture seule : 8Assembleur 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 : ", 0Lecture seule : 83,22 Check End of File. Officiel
Indique si un canal ouvert est arrivé à la fin de son fichier.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du canal |
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | non 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;
}8 octets lus avant la fin du fichierMad 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.8 octets lus avant la fin du fichierNeoBASIC
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"8 octets lus avant la fin du fichierAssembleur 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, 08 octets lus avant la fin du fichier3,23 Get Current Working Directory. Modifié par Trinity
Copie le chemin du répertoire courant dans un tampon.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du tampon |
P2 | uint8 | longueur maximale du chemin |
| Octets | Type | Rôle |
|---|---|---|
tampon | string | chemin (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;
}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.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$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 : ", 0Repertoire 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).
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du volume (0 à 3) |
P1-P2 | addr | adresse du tampon du nom ; son premier octet donne sa capacité |
| Octets | Type | Rôle |
|---|---|---|
tampon | string | nom du volume (précédé de sa longueur) |
P3 | uint8 | attributs : bit 0 présent, bit 1 lecture seule, bit 2 réseau |
erreur | uint8 | non 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;
}Volume 0 : HOST0Mad 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.Volume 0 : HOST0NeoBASIC
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 vVolume 0 : HOST0Assembleur 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 " : ", 0Volume 0 : HOST03,25 Select Volume Trinity
Fait d'un volume le volume courant : les chemins sans préfixe « n: » s'y rapportent ensuite.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du volume (0 à 3) |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | non 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;
}Volume 0 choisi, erreur 0, volume courant : 0Mad 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.Volume 0 choisi, erreur 0, volume courant : 0NeoBASIC
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 : ";vVolume 0 choisi, erreur 0, volume courant : 0Assembleur 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 : ", 0Volume 0 choisi, erreur 0, volume courant : 03,26 Get Current Volume Trinity
Donne le numéro du volume courant.
Entrées : aucune.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numé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;
}Volume courant : 0Mad 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.Volume courant : 0NeoBASIC
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 : ";vVolume courant : 0Assembleur 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 : ", 0Volume courant : 03,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.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du canal |
P1 | uint8 | page : $00 mémoire du 6502, $80 et $81 mémoire vidéo, $90 mémoire graphique (comme 12,2) |
P2-P3 | addr | adresse dans la page |
P4-P5 | uint16 | nombre d'octets demandés |
| Octets | Type | Rôle |
|---|---|---|
P4-P5 | uint16 | nombre 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;
}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.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)"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, 0Lu 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.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro du canal |
P1 | uint8 | page : $00 mémoire du 6502, $80 et $81 mémoire vidéo, $90 mémoire graphique (comme 3,27) |
P2-P3 | addr | adresse dans la page |
P4-P5 | uint16 | nombre d'octets demandés |
P6-P7 | addr | adresse des 3 octets de suivi (mémoire du 6502) |
| Octets | Type | Rôle |
|---|---|---|
suivi+0 | uint8 | $01 pendant la lecture, puis $80 + code d'erreur ($80 : réussi) |
suivi+1-2 | uint16 | nombre d'octets lus |
erreur | uint8 | seulement 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;
}Lu : ABCDEFGH, etat 128, 8 octets
Suivi dans la cible : erreur 21Mad 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.Lu : ABCDEFGH, etat 128, 8 octets
Suivi dans la cible : erreur 21NeoBASIC
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 returnLu : ABCDEFGH, etat 128, 8 octets
Suivi dans la cible : erreur 21Assembleur 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 0Lu : ABCDEFGH, etat 128, 8 octets
Suivi dans la cible : erreur 213,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.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | uint16 | date : bits 15-9 année - 1980, 8-5 mois, 4-0 jour ; 0 si inconnue |
P2-P3 | uint16 | heure : bits 15-11 heure, 10-5 minutes, 4-0 secondes / 2 ; 0 si inconnue |
erreur | uint8 | 1 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;
}abc.txt : 2026-10-03 15:19:38Mad 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.abc.txt : 2026-10-03 15:19:36NeoBASIC
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 returnabc.txt : 2026-10-03 15:19:38Assembleur 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 0abc.txt : 2026-10-03 15:19:363,32 List Filtered Officiel
Affiche la liste des fichiers du répertoire courant dont le nom contient un texte donné.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse 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;
}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.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"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"abc.txt 8 bytes.