Groupe 38 — Gestionnaire de ressources Trinity
38,1 Open Resource File · 38,2 Close Resource File · 38,3 Count Resources · 38,4 Find Resource · 38,5 Get Resource Info · 38,6 Get Resource Size · 38,7 Load Resource · 38,8 Use Font
Le gestionnaire de ressources de la boîte à outils de Trinity lit des fichiers de ressources au format NR1 : un en-tête (« NR », version 1, nombre de ressources), une table de 16 octets par ressource (type de 4 caractères, identifiant sur 16 bits, décalage et taille sur 32 bits), puis les données. Ils se fabriquent avec tools/toolbox/mkres.py, dans le dépôt de Trinity.
Les exemples utilisent demo.res, posé à la racine du stockage et fabriqué ainsi : mkres.py demo.res TEXT:1:bonjour.txt FONT:1:cadre.nf1 TEXT:2:neo.txt, où bonjour.txt contient « Bonjour », neo.txt « Neo6502 ! » et cadre.nf1 la police d'un caractère de l'exemple 32,15 (17 octets). Les exemples l'ouvrent sur le canal de fichier 1.
38,1 Open Resource File Trinity
Ouvre un fichier de ressources NR1 sur un canal de fichier.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | canal de fichier |
P1-P2 | addr | adresse du nom, précédé de sa longueur |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | 1 canal invalide ou pas un fichier de ressources, 2 erreur de stockage |
Un seul fichier de ressources est ouvert à la fois : en ouvrir un autre ferme le premier. Rien n'est gardé côté RP2040 : la table est relue sur le stockage à chaque appel. Au banc, un fichier absent rend l'erreur 2. NeoBASIC n'a pas de mot-clé pour cet appel.
Texte de la documentation du firmware (anglais)
Toolbox (Trinity, T-12, ADR-01 of the fork). Opens on file channel Parameter:0 the resource file whose length-prefixed name is at Parameters:1,2 (format NR1, built by tools/mkres.py of the fork archive : a table of resources, each with a 4 character type, a 16 bit id, an offset and a size, then the data). One resource file is open at a time (opening another closes it) ; nothing is cached in the RP2040, the table is read from storage on each call. Errors : 1 bad channel or not a resource file, 2 storage error. Resources are numbered 1..count in table order.
C (llvm-mos)
/* Ouvrir un fichier de ressources (groupe 38, fonction 1, 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)
;
}
/* demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ». */
static const char demo[] = "\010demo.res"; /* nom précédé de sa longueur */
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
static uint8_t res(uint8_t f) { /* appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(38, f);
return ControlPort.error;
}
static uint8_t ouvrir(const char *nom) { /* 38,1 Open Resource File, sur le canal de fichier 1 */
libre();
ControlPort.params[0] = 1;
p16(1, (uint16_t)nom);
return res(1);
}
static void fermer(void) { /* 38,2 Close Resource File */
libre();
res(2);
}
static const char absent[] = "\010rien.res";
int main(void) {
uint8_t e1, e2, n;
e1 = ouvrir(absent); /* fichier absent : erreur de stockage */
e2 = ouvrir(demo);
libre(); res(3); n = ControlPort.params[0]; /* 38,3 : nombre de ressources */
fermer();
printf("Fichier absent : erreur %u\ndemo.res : erreur %u, %u ressources\n", e1, e2, n);
return 0;
}Fichier absent : erreur 2
demo.res : erreur 0, 3 ressourcesMad Pascal
// Ouvrir un fichier de ressources (groupe 38, fonction 1, Trinity).
program rs1;
uses crt, neo6502;
// demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
// caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
const demo: array[0..8] of byte = (8, ord('d'), ord('e'), ord('m'), ord('o'), ord('.'), ord('r'), ord('e'), ord('s'));
function res(f: byte): byte; // appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(38, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function ouvrir(nom: pointer): byte; // 38,1 Open Resource File, sur le canal de fichier 1
begin
NeoWaitMessage;
NeoMessage.params[0] := 1;
NeoMessage.params[1] := lo(word(nom));
NeoMessage.params[2] := hi(word(nom));
result := res(1);
end;
procedure fermer; // 38,2 Close Resource File
begin
NeoWaitMessage;
res(2);
end;
const absent: array[0..8] of byte = (8, ord('r'), ord('i'), ord('e'), ord('n'), ord('.'), ord('r'), ord('e'), ord('s'));
var e1, e2, n: byte;
begin
e1 := ouvrir(@absent); // fichier absent : erreur de stockage
e2 := ouvrir(@demo);
res(3); n := NeoMessage.params[0]; // 38,3 : nombre de ressources
fermer;
writeln('Fichier absent : erreur ', e1);
writeln('demo.res : erreur ', e2, ', ', n, ' ressources');
end.Fichier absent : erreur 2
demo.res : erreur 0, 3 ressourcesNeoBASIC
10 ' Ouvrir un fichier de ressources (groupe 38, fonction 1, Trinity)
15 ' demo.res (fabrique avec tools/toolbox/mkres.py de Trinity) : TEXT 1, FONT 1, TEXT 2
20 s$ = "rien.res" : gosub 8900 : gosub 8000 : e1 = e : ' fichier absent : erreur de stockage
30 s$ = "demo.res" : gosub 8900 : gosub 8000 : e2 = e
40 while peek($ff00) : wend : f = 3 : gosub 8110 : n = peek($ff04) : ' 38,3 : nombre de ressources
50 gosub 8200
60 print "Fichier absent : erreur ";e1
70 print "demo.res : erreur ";e2;", ";n;" ressources"
80 end
8000 ' 38,1 Open Resource File sur le canal 1 : nom precede de sa longueur en nm ; erreur dans e
8010 while peek($ff00) : wend : poke $ff04, 1 : doke $ff05, nm : f = 1
8100 ' appel 38,f, parametres deja poses ; erreur dans e
8110 poke $ff01, f : poke $ff00, 38
8120 while peek($ff00) : wend : e = peek($ff02) : return
8200 ' 38,2 Close Resource File
8210 while peek($ff00) : wend : f = 2 : goto 8110
8900 ' chaine s$ precedee de sa longueur, dans un bloc neuf nm
8910 nm = alloc(len(s$) + 1) : poke nm, len(s$) : for i = 1 to len(s$) : poke nm + i, asc(mid$(s$, i, 1)) : next i : returnFichier absent : erreur 2
demo.res : erreur 0, 3 ressourcesAssembleur 65C02 (64tass)
; Ouvrir un fichier de ressources (groupe 38, fonction 1, 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: lda #<absent
ldx #>absent
jsr ouvrir ; fichier absent : erreur de stockage
sta e1
lda #<demo
ldx #>demo
jsr ouvrir
sta e2
jsr WaitMessage
ldx #3 ; 38,3 : nombre de ressources
jsr res
lda ControlPort+4
sta n
jsr WaitMessage
ldx #2 ; 38,2 Close Resource File
jsr res
lda #<t0
ldx #>t0
jsr ecrire
lda e1
jsr decimal
lda #13
jsr WriteCharacter
lda #<t1
ldx #>t1
jsr ecrire
lda e2
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda n
jsr decimal
lda #<t3
ldx #>t3
jsr ecrire
lda #13
jsr WriteCharacter
rts
; demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
; caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
demo: .byte 8
.text "demo.res" ; nom précédé de sa longueur
absent: .byte 8
.text "rien.res"
e1: .byte 0
e2: .byte 0
n: .byte 0
t0: .text "Fichier absent : erreur ", 0
t1: .text "demo.res : erreur ", 0
t2: .text ", ", 0
t3: .text " ressources", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
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
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; 38,1 Open Resource File, sur le canal de fichier 1 : nom en A (poids faible) et X (poids fort) ; erreur dans A.
ouvrir: pha
phx
jsr WaitMessage
lda #1
sta ControlPort+4
plx
stx ControlPort+6
pla
sta ControlPort+5
ldx #1
; Appel 38,X (paramètres déjà posés) ; rend l'indicateur d'erreur dans A.
res: lda #38
jsr appel
lda ControlPort+2
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
blk = $82
diviseur: .byte 0
fin: .byte 0Fichier absent : erreur 2
demo.res : erreur 0, 3 ressources38,2 Close Resource File Trinity
Ferme le fichier de ressources et son canal.
Entrées : aucune.
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | 1 si aucun fichier n'est ouvert |
Après la fermeture, les autres fonctions du groupe rendent l'erreur 1. NeoBASIC n'a pas de mot-clé pour cet appel.
Texte de la documentation du firmware (anglais)
Closes the resource file and its channel (error 1 if none is open).
C (llvm-mos)
/* Fermer le fichier de ressources (groupe 38, fonction 2, 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)
;
}
/* demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ». */
static const char demo[] = "\010demo.res"; /* nom précédé de sa longueur */
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
static uint8_t res(uint8_t f) { /* appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(38, f);
return ControlPort.error;
}
static uint8_t ouvrir(const char *nom) { /* 38,1 Open Resource File, sur le canal de fichier 1 */
libre();
ControlPort.params[0] = 1;
p16(1, (uint16_t)nom);
return res(1);
}
static void fermer(void) { /* 38,2 Close Resource File */
libre();
res(2);
}
int main(void) {
uint8_t e1, e2, e3;
ouvrir(demo);
libre(); e1 = res(2); /* Close Resource File : ferme aussi le canal */
libre(); e2 = res(2); /* plus rien d'ouvert */
libre(); e3 = res(3);
printf("Fermeture : erreur %u ; encore : erreur %u\nCompter ensuite : erreur %u\n", e1, e2, e3);
return 0;
}Fermeture : erreur 0 ; encore : erreur 1
Compter ensuite : erreur 1Mad Pascal
// Fermer le fichier de ressources (groupe 38, fonction 2, Trinity).
program rs2;
uses crt, neo6502;
// demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
// caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
const demo: array[0..8] of byte = (8, ord('d'), ord('e'), ord('m'), ord('o'), ord('.'), ord('r'), ord('e'), ord('s'));
function res(f: byte): byte; // appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(38, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function ouvrir(nom: pointer): byte; // 38,1 Open Resource File, sur le canal de fichier 1
begin
NeoWaitMessage;
NeoMessage.params[0] := 1;
NeoMessage.params[1] := lo(word(nom));
NeoMessage.params[2] := hi(word(nom));
result := res(1);
end;
procedure fermer; // 38,2 Close Resource File
begin
NeoWaitMessage;
res(2);
end;
var e1, e2, e3: byte;
begin
ouvrir(@demo);
e1 := res(2); // Close Resource File : ferme aussi le canal
e2 := res(2); // plus rien d'ouvert
e3 := res(3);
writeln('Fermeture : erreur ', e1, ' ; encore : erreur ', e2);
writeln('Compter ensuite : erreur ', e3);
end.Fermeture : erreur 0 ; encore : erreur 1
Compter ensuite : erreur 1NeoBASIC
10 ' Fermer le fichier de ressources (groupe 38, fonction 2, Trinity)
15 ' demo.res (fabrique avec tools/toolbox/mkres.py de Trinity) : TEXT 1, FONT 1, TEXT 2
20 s$ = "demo.res" : gosub 8900 : gosub 8000
30 gosub 8200 : e1 = e : ' Close Resource File : ferme aussi le canal
40 gosub 8200 : e2 = e : ' plus rien d'ouvert
50 while peek($ff00) : wend : f = 3 : gosub 8110 : e3 = e
60 print "Fermeture : erreur ";e1;" ; encore : erreur ";e2
70 print "Compter ensuite : erreur ";e3
80 end
8000 ' 38,1 Open Resource File sur le canal 1 : nom precede de sa longueur en nm ; erreur dans e
8010 while peek($ff00) : wend : poke $ff04, 1 : doke $ff05, nm : f = 1
8100 ' appel 38,f, parametres deja poses ; erreur dans e
8110 poke $ff01, f : poke $ff00, 38
8120 while peek($ff00) : wend : e = peek($ff02) : return
8200 ' 38,2 Close Resource File
8210 while peek($ff00) : wend : f = 2 : goto 8110
8900 ' chaine s$ precedee de sa longueur, dans un bloc neuf nm
8910 nm = alloc(len(s$) + 1) : poke nm, len(s$) : for i = 1 to len(s$) : poke nm + i, asc(mid$(s$, i, 1)) : next i : returnFermeture : erreur 0 ; encore : erreur 1
Compter ensuite : erreur 1Assembleur 65C02 (64tass)
; Fermer le fichier de ressources (groupe 38, fonction 2, 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: lda #<demo
ldx #>demo
jsr ouvrir
jsr WaitMessage
ldx #2 ; Close Resource File : ferme aussi le canal
jsr res
sta e1
jsr WaitMessage
ldx #2 ; plus rien d'ouvert
jsr res
sta e2
jsr WaitMessage
ldx #3 ; 38,3
jsr res
sta e3
lda #<t0
ldx #>t0
jsr ecrire
lda e1
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
lda e2
jsr decimal
lda #13
jsr WriteCharacter
lda #<t2
ldx #>t2
jsr ecrire
lda e3
jsr decimal
lda #13
jsr WriteCharacter
rts
; demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
; caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
demo: .byte 8
.text "demo.res" ; nom précédé de sa longueur
e1: .byte 0
e2: .byte 0
e3: .byte 0
t0: .text "Fermeture : erreur ", 0
t1: .text " ; encore : erreur ", 0
t2: .text "Compter ensuite : erreur ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
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
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; 38,1 Open Resource File, sur le canal de fichier 1 : nom en A (poids faible) et X (poids fort) ; erreur dans A.
ouvrir: pha
phx
jsr WaitMessage
lda #1
sta ControlPort+4
plx
stx ControlPort+6
pla
sta ControlPort+5
ldx #1
; Appel 38,X (paramètres déjà posés) ; rend l'indicateur d'erreur dans A.
res: lda #38
jsr appel
lda ControlPort+2
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
blk = $82
diviseur: .byte 0
fin: .byte 0Fermeture : erreur 0 ; encore : erreur 1
Compter ensuite : erreur 138,3 Count Resources Trinity
Rend le nombre de ressources du fichier ouvert.
Entrées : aucune.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | nombre de ressources |
Les ressources sont numérotées de 1 à ce nombre, dans l'ordre de la table. NeoBASIC n'a pas de mot-clé pour cet appel.
Texte de la documentation du firmware (anglais)
Returns the number of resources of the open file in Parameter:0.
C (llvm-mos)
/* Compter les ressources (groupe 38, fonction 3, 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)
;
}
/* demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ». */
static const char demo[] = "\010demo.res"; /* nom précédé de sa longueur */
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
static uint8_t res(uint8_t f) { /* appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(38, f);
return ControlPort.error;
}
static uint8_t ouvrir(const char *nom) { /* 38,1 Open Resource File, sur le canal de fichier 1 */
libre();
ControlPort.params[0] = 1;
p16(1, (uint16_t)nom);
return res(1);
}
static void fermer(void) { /* 38,2 Close Resource File */
libre();
res(2);
}
int main(void) {
uint8_t n;
ouvrir(demo);
libre(); res(3); /* Count Resources : numérotées de 1 à n */
n = ControlPort.params[0];
fermer();
printf("Ressources : %u\n", n);
return 0;
}Ressources : 3Mad Pascal
// Compter les ressources (groupe 38, fonction 3, Trinity).
program rs3;
uses crt, neo6502;
// demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
// caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
const demo: array[0..8] of byte = (8, ord('d'), ord('e'), ord('m'), ord('o'), ord('.'), ord('r'), ord('e'), ord('s'));
function res(f: byte): byte; // appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(38, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function ouvrir(nom: pointer): byte; // 38,1 Open Resource File, sur le canal de fichier 1
begin
NeoWaitMessage;
NeoMessage.params[0] := 1;
NeoMessage.params[1] := lo(word(nom));
NeoMessage.params[2] := hi(word(nom));
result := res(1);
end;
procedure fermer; // 38,2 Close Resource File
begin
NeoWaitMessage;
res(2);
end;
var n: byte;
begin
ouvrir(@demo);
res(3); // Count Resources : numérotées de 1 à n
n := NeoMessage.params[0];
fermer;
writeln('Ressources : ', n);
end.Ressources : 3NeoBASIC
10 ' Compter les ressources (groupe 38, fonction 3, Trinity)
15 ' demo.res (fabrique avec tools/toolbox/mkres.py de Trinity) : TEXT 1, FONT 1, TEXT 2
20 s$ = "demo.res" : gosub 8900 : gosub 8000
30 while peek($ff00) : wend : f = 3 : gosub 8110 : n = peek($ff04) : ' Count Resources : numerotees de 1 a n
40 gosub 8200
50 print "Ressources : ";n
60 end
8000 ' 38,1 Open Resource File sur le canal 1 : nom precede de sa longueur en nm ; erreur dans e
8010 while peek($ff00) : wend : poke $ff04, 1 : doke $ff05, nm : f = 1
8100 ' appel 38,f, parametres deja poses ; erreur dans e
8110 poke $ff01, f : poke $ff00, 38
8120 while peek($ff00) : wend : e = peek($ff02) : return
8200 ' 38,2 Close Resource File
8210 while peek($ff00) : wend : f = 2 : goto 8110
8900 ' chaine s$ precedee de sa longueur, dans un bloc neuf nm
8910 nm = alloc(len(s$) + 1) : poke nm, len(s$) : for i = 1 to len(s$) : poke nm + i, asc(mid$(s$, i, 1)) : next i : returnRessources : 3Assembleur 65C02 (64tass)
; Compter les ressources (groupe 38, fonction 3, 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: lda #<demo
ldx #>demo
jsr ouvrir
jsr WaitMessage
ldx #3 ; Count Resources : numérotées de 1 à n
jsr res
lda ControlPort+4
sta n
jsr WaitMessage
ldx #2 ; 38,2 Close Resource File
jsr res
lda #<t0
ldx #>t0
jsr ecrire
lda n
jsr decimal
lda #13
jsr WriteCharacter
rts
; demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
; caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
demo: .byte 8
.text "demo.res" ; nom précédé de sa longueur
n: .byte 0
t0: .text "Ressources : ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
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
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; 38,1 Open Resource File, sur le canal de fichier 1 : nom en A (poids faible) et X (poids fort) ; erreur dans A.
ouvrir: pha
phx
jsr WaitMessage
lda #1
sta ControlPort+4
plx
stx ControlPort+6
pla
sta ControlPort+5
ldx #1
; Appel 38,X (paramètres déjà posés) ; rend l'indicateur d'erreur dans A.
res: lda #38
jsr appel
lda ControlPort+2
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
blk = $82
diviseur: .byte 0
fin: .byte 0Ressources : 338,4 Find Resource Trinity
Cherche une ressource par son type et son identifiant.
| Octets | Type | Rôle |
|---|---|---|
P0-P3 | uint8 | type : 4 caractères ASCII, complétés par des espaces |
P4-P5 | uint16 | identifiant |
| Octets | Type | Rôle |
|---|---|---|
P6 | uint8 | numéro de la ressource (0 si absente) |
erreur | uint8 | 3 si la ressource est absente |
NeoBASIC n'a pas de mot-clé pour cet appel.
Texte de la documentation du firmware (anglais)
Looks for the resource of type Parameters:0-3 (4 ASCII characters, padded with spaces) and id Parameters:4,5 ; returns its number in Parameter:6 (0 and error 3 if not found).
C (llvm-mos)
/* Chercher une ressource par type et numéro (groupe 38, fonction 4, 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)
;
}
/* demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ». */
static const char demo[] = "\010demo.res"; /* nom précédé de sa longueur */
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
static uint8_t res(uint8_t f) { /* appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(38, f);
return ControlPort.error;
}
static uint8_t ouvrir(const char *nom) { /* 38,1 Open Resource File, sur le canal de fichier 1 */
libre();
ControlPort.params[0] = 1;
p16(1, (uint16_t)nom);
return res(1);
}
static void fermer(void) { /* 38,2 Close Resource File */
libre();
res(2);
}
static uint8_t chercher(const char *type, uint16_t id) { /* Find Resource : type de 4 caractères, id */
uint8_t i;
libre();
for (i = 0; i < 4; i++)
ControlPort.params[i] = type[i];
p16(4, id);
res(4);
return ControlPort.params[6]; /* numéro de la ressource, 0 si absente */
}
int main(void) {
uint8_t f, t, n, e;
ouvrir(demo);
f = chercher("FONT", 1);
t = chercher("TEXT", 2);
n = chercher("TEXT", 9);
e = ControlPort.error;
fermer();
printf("FONT 1 : %u, TEXT 2 : %u, TEXT 9 : %u (erreur %u)\n", f, t, n, e);
return 0;
}FONT 1 : 2, TEXT 2 : 3, TEXT 9 : 0 (erreur 3)Mad Pascal
// Chercher une ressource par type et numéro (groupe 38, fonction 4, Trinity).
program rs4;
uses crt, neo6502;
// demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
// caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
const demo: array[0..8] of byte = (8, ord('d'), ord('e'), ord('m'), ord('o'), ord('.'), ord('r'), ord('e'), ord('s'));
function res(f: byte): byte; // appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(38, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function ouvrir(nom: pointer): byte; // 38,1 Open Resource File, sur le canal de fichier 1
begin
NeoWaitMessage;
NeoMessage.params[0] := 1;
NeoMessage.params[1] := lo(word(nom));
NeoMessage.params[2] := hi(word(nom));
result := res(1);
end;
procedure fermer; // 38,2 Close Resource File
begin
NeoWaitMessage;
res(2);
end;
function chercher(a, b, c, d: char; id: word): byte; // Find Resource : type de 4 caractères, id
begin
NeoWaitMessage;
NeoMessage.params[0] := ord(a); NeoMessage.params[1] := ord(b);
NeoMessage.params[2] := ord(c); NeoMessage.params[3] := ord(d);
NeoMessage.params[4] := lo(id); NeoMessage.params[5] := hi(id);
res(4);
result := NeoMessage.params[6]; // numéro de la ressource, 0 si absente
end;
var f, t, n, e: byte;
begin
ouvrir(@demo);
f := chercher('F', 'O', 'N', 'T', 1);
t := chercher('T', 'E', 'X', 'T', 2);
n := chercher('T', 'E', 'X', 'T', 9);
e := NeoMessage.error;
fermer;
writeln('FONT 1 : ', f, ', TEXT 2 : ', t, ', TEXT 9 : ', n, ' (erreur ', e, ')');
end.FONT 1 : 2, TEXT 2 : 3, TEXT 9 : 0 (erreur 3)NeoBASIC
10 ' Chercher une ressource par type et numero (groupe 38, fonction 4, Trinity)
15 ' demo.res (fabrique avec tools/toolbox/mkres.py de Trinity) : TEXT 1, FONT 1, TEXT 2
20 s$ = "demo.res" : gosub 8900 : gosub 8000
30 t$ = "FONT" : id = 1 : gosub 2000 : fo = r
40 t$ = "TEXT" : id = 2 : gosub 2000 : tx = r
50 id = 9 : gosub 2000 : n = r : e9 = e
60 gosub 8200
70 print "FONT 1 : ";fo;", TEXT 2 : ";tx;", TEXT 9 : ";n;" (erreur ";e9;")"
80 end
2000 ' Find Resource : type t$ (4 caracteres), id ; numero dans r, 0 si absente
2010 while peek($ff00) : wend : for i = 1 to 4 : poke $ff03 + i, asc(mid$(t$, i, 1)) : next i : doke $ff08, id
2020 f = 4 : gosub 8110 : r = peek($ff0a) : return
8000 ' 38,1 Open Resource File sur le canal 1 : nom precede de sa longueur en nm ; erreur dans e
8010 while peek($ff00) : wend : poke $ff04, 1 : doke $ff05, nm : f = 1
8100 ' appel 38,f, parametres deja poses ; erreur dans e
8110 poke $ff01, f : poke $ff00, 38
8120 while peek($ff00) : wend : e = peek($ff02) : return
8200 ' 38,2 Close Resource File
8210 while peek($ff00) : wend : f = 2 : goto 8110
8900 ' chaine s$ precedee de sa longueur, dans un bloc neuf nm
8910 nm = alloc(len(s$) + 1) : poke nm, len(s$) : for i = 1 to len(s$) : poke nm + i, asc(mid$(s$, i, 1)) : next i : returnFONT 1 : 2, TEXT 2 : 3, TEXT 9 : 0 (erreur 3)Assembleur 65C02 (64tass)
; Chercher une ressource par type et numéro (groupe 38, fonction 4, 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: lda #<demo
ldx #>demo
jsr ouvrir
lda #<b0
ldx #>b0
jsr envoi
lda ControlPort+10 ; P6 : numéro, 0 si absente
sta fo
lda #<b1
ldx #>b1
jsr envoi
lda ControlPort+10 ; P6 : numéro, 0 si absente
sta tx
lda #<b2
ldx #>b2
jsr envoi
lda ControlPort+10 ; P6 : numéro, 0 si absente
sta n
lda ControlPort+2
sta e
jsr WaitMessage
ldx #2 ; 38,2 Close Resource File
jsr res
lda #<t3
ldx #>t3
jsr ecrire
lda fo
jsr decimal
lda #<t4
ldx #>t4
jsr ecrire
lda tx
jsr decimal
lda #<t5
ldx #>t5
jsr ecrire
lda n
jsr decimal
lda #<t6
ldx #>t6
jsr ecrire
lda e
jsr decimal
lda #<t7
ldx #>t7
jsr ecrire
lda #13
jsr WriteCharacter
rts
; demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
; caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
demo: .byte 8
.text "demo.res" ; nom précédé de sa longueur
b0: .byte 38, 4, 6 ; Find Resource : FONT 1
.text "FONT"
.word 1
fo: .byte 0
b1: .byte 38, 4, 6 ; Find Resource : TEXT 2
.text "TEXT"
.word 2
tx: .byte 0
b2: .byte 38, 4, 6 ; Find Resource : TEXT 9
.text "TEXT"
.word 9
n: .byte 0
e: .byte 0
t3: .text "FONT 1 : ", 0
t4: .text ", TEXT 2 : ", 0
t5: .text ", TEXT 9 : ", 0
t6: .text " (erreur ", 0
t7: .text ")", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
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
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; 38,1 Open Resource File, sur le canal de fichier 1 : nom en A (poids faible) et X (poids fort) ; erreur dans A.
ouvrir: pha
phx
jsr WaitMessage
lda #1
sta ControlPort+4
plx
stx ControlPort+6
pla
sta ControlPort+5
ldx #1
; Appel 38,X (paramètres déjà posés) ; rend l'indicateur d'erreur dans A.
res: lda #38
jsr appel
lda ControlPort+2
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
blk = $82
diviseur: .byte 0
fin: .byte 0FONT 1 : 2, TEXT 2 : 3, TEXT 9 : 0 (erreur 3)38,5 Get Resource Info Trinity
Rend le type et l'identifiant d'une ressource.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro de la ressource (1 à n, dans l'ordre de la table) |
| Octets | Type | Rôle |
|---|---|---|
P1-P4 | uint8 | type (4 caractères) |
P5-P6 | uint16 | identifiant |
erreur | uint8 | 3 si le numéro est hors de la table |
Avec 38,3, permet de parcourir toute la table. NeoBASIC n'a pas de mot-clé pour cet appel.
Texte de la documentation du firmware (anglais)
Returns the type of resource Parameter:0 in Parameters:1-4 and its id in Parameters:5,6 (error 3 if the number is out of range).
C (llvm-mos)
/* Lire le type et l'identifiant d'une ressource (groupe 38, fonction 5, 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)
;
}
/* demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ». */
static const char demo[] = "\010demo.res"; /* nom précédé de sa longueur */
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
static uint8_t res(uint8_t f) { /* appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(38, f);
return ControlPort.error;
}
static uint8_t ouvrir(const char *nom) { /* 38,1 Open Resource File, sur le canal de fichier 1 */
libre();
ControlPort.params[0] = 1;
p16(1, (uint16_t)nom);
return res(1);
}
static void fermer(void) { /* 38,2 Close Resource File */
libre();
res(2);
}
int main(void) {
uint8_t i, j, e, t[3][4];
uint16_t id[3];
ouvrir(demo);
for (i = 0; i < 3; i++) {
libre();
ControlPort.params[0] = i + 1;
res(5); /* Get Resource Info */
for (j = 0; j < 4; j++)
t[i][j] = ControlPort.params[1 + j]; /* type en P1-P4 */
id[i] = ControlPort.params[5] | ControlPort.params[6] << 8; /* id en P5-P6 */
}
libre(); ControlPort.params[0] = 4; e = res(5); /* hors de la table */
fermer();
for (i = 0; i < 3; i++)
printf("%u : %c%c%c%c %u\n", i + 1, t[i][0], t[i][1], t[i][2], t[i][3], id[i]);
printf("4 : erreur %u\n", e);
return 0;
}1 : TEXT 1
2 : FONT 1
3 : TEXT 2
4 : erreur 3Mad Pascal
// Lire le type et l'identifiant d'une ressource (groupe 38, fonction 5, Trinity).
program rs5;
uses crt, neo6502;
// demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
// caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
const demo: array[0..8] of byte = (8, ord('d'), ord('e'), ord('m'), ord('o'), ord('.'), ord('r'), ord('e'), ord('s'));
function res(f: byte): byte; // appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(38, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function ouvrir(nom: pointer): byte; // 38,1 Open Resource File, sur le canal de fichier 1
begin
NeoWaitMessage;
NeoMessage.params[0] := 1;
NeoMessage.params[1] := lo(word(nom));
NeoMessage.params[2] := hi(word(nom));
result := res(1);
end;
procedure fermer; // 38,2 Close Resource File
begin
NeoWaitMessage;
res(2);
end;
var i, j, e: byte;
t: array[0..11] of byte;
id: array[0..2] of word;
begin
ouvrir(@demo);
for i := 0 to 2 do begin
NeoWaitMessage;
NeoMessage.params[0] := i + 1;
res(5); // Get Resource Info
for j := 0 to 3 do t[i * 4 + j] := NeoMessage.params[1 + j]; // type en P1-P4
id[i] := NeoMessage.params[5] + NeoMessage.params[6] shl 8; // id en P5-P6
end;
NeoMessage.params[0] := 4; e := res(5); // hors de la table
fermer;
for i := 0 to 2 do
writeln(i + 1, ' : ', chr(t[i * 4]), chr(t[i * 4 + 1]), chr(t[i * 4 + 2]), chr(t[i * 4 + 3]), ' ', id[i]);
writeln('4 : erreur ', e);
end.1 : TEXT 1
2 : FONT 1
3 : TEXT 2
4 : erreur 3NeoBASIC
10 ' Lire le type et l'identifiant d'une ressource (groupe 38, fonction 5, Trinity)
15 ' demo.res (fabrique avec tools/toolbox/mkres.py de Trinity) : TEXT 1, FONT 1, TEXT 2
20 s$ = "demo.res" : gosub 8900 : gosub 8000
30 dim t$(2), id(2)
40 for k = 0 to 2
50 while peek($ff00) : wend : poke $ff04, k + 1 : f = 5 : gosub 8110 : ' Get Resource Info
60 t$(k) = "" : for i = 0 to 3 : t$(k) = t$(k) + chr$(peek($ff05 + i)) : next i : ' type en P1-P4
70 id(k) = deek($ff09) : next k : ' id en P5-P6
80 while peek($ff00) : wend : poke $ff04, 4 : f = 5 : gosub 8110 : e4 = e : ' hors de la table
90 gosub 8200
100 for k = 0 to 2 : print k + 1;" : ";t$(k);" ";id(k) : next k
110 print "4 : erreur ";e4
120 end
8000 ' 38,1 Open Resource File sur le canal 1 : nom precede de sa longueur en nm ; erreur dans e
8010 while peek($ff00) : wend : poke $ff04, 1 : doke $ff05, nm : f = 1
8100 ' appel 38,f, parametres deja poses ; erreur dans e
8110 poke $ff01, f : poke $ff00, 38
8120 while peek($ff00) : wend : e = peek($ff02) : return
8200 ' 38,2 Close Resource File
8210 while peek($ff00) : wend : f = 2 : goto 8110
8900 ' chaine s$ precedee de sa longueur, dans un bloc neuf nm
8910 nm = alloc(len(s$) + 1) : poke nm, len(s$) : for i = 1 to len(s$) : poke nm + i, asc(mid$(s$, i, 1)) : next i : return1 : TEXT 1
2 : FONT 1
3 : TEXT 2
4 : erreur 3Assembleur 65C02 (64tass)
; Lire le type et l'identifiant d'une ressource (groupe 38, fonction 5, 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: lda #<demo
ldx #>demo
jsr ouvrir
ldx #0 ; ressource 1, 2, 3
ldy #0 ; place dans info
_r: phx
phy
jsr WaitMessage
plx
pla
pha
phx
inc a
sta ControlPort+4
ldx #5 ; Get Resource Info : type en P1-P4, id en P5-P6
jsr res
ply
ldx #0
_c: lda ControlPort+5,x
sta info,y
iny
inx
cpx #6
bne _c
plx
inx
cpx #3
bne _r
jsr WaitMessage
lda #4 ; hors de la table
sta ControlPort+4
ldx #5 ; 38,5
jsr res
sta e
jsr WaitMessage
ldx #2 ; 38,2 Close Resource File
jsr res
lda #<t0
ldx #>t0
jsr ecrire
ldx #0
_t0: lda info,x
jsr WriteCharacter
inx
cpx #4
bne _t0
lda #' '
jsr WriteCharacter
lda info+4
ldx info+4+1
jsr dec16
lda #13
jsr WriteCharacter
lda #<t1
ldx #>t1
jsr ecrire
ldx #6
_t1: lda info,x
jsr WriteCharacter
inx
cpx #10
bne _t1
lda #' '
jsr WriteCharacter
lda info+10
ldx info+10+1
jsr dec16
lda #13
jsr WriteCharacter
lda #<t2
ldx #>t2
jsr ecrire
ldx #12
_t2: lda info,x
jsr WriteCharacter
inx
cpx #16
bne _t2
lda #' '
jsr WriteCharacter
lda info+16
ldx info+16+1
jsr dec16
lda #13
jsr WriteCharacter
lda #<t3
ldx #>t3
jsr ecrire
lda e
jsr decimal
lda #13
jsr WriteCharacter
rts
; demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
; caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
demo: .byte 8
.text "demo.res" ; nom précédé de sa longueur
info: .fill 18 ; 3 × (type sur 4 octets, id sur 2)
e: .byte 0
t0: .text "1 : ", 0
t1: .text "2 : ", 0
t2: .text "3 : ", 0
t3: .text "4 : erreur ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
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
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; 38,1 Open Resource File, sur le canal de fichier 1 : nom en A (poids faible) et X (poids fort) ; erreur dans A.
ouvrir: pha
phx
jsr WaitMessage
lda #1
sta ControlPort+4
plx
stx ControlPort+6
pla
sta ControlPort+5
ldx #1
; Appel 38,X (paramètres déjà posés) ; rend l'indicateur d'erreur dans A.
res: lda #38
jsr appel
lda ControlPort+2
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
blk = $82
diviseur: .byte 0
fin: .byte 01 : TEXT 1
2 : FONT 1
3 : TEXT 2
4 : erreur 338,6 Get Resource Size Trinity
Rend la taille d'une ressource en octets.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro de la ressource (1 à n, dans l'ordre de la table) |
| Octets | Type | Rôle |
|---|---|---|
P1-P4 | uint32 | taille en octets |
NeoBASIC n'a pas de mot-clé pour cet appel.
Texte de la documentation du firmware (anglais)
Returns the size in bytes of resource Parameter:0 in Parameters:1-4 (32 bits).
C (llvm-mos)
/* Lire la taille d'une ressource (groupe 38, fonction 6, 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)
;
}
/* demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ». */
static const char demo[] = "\010demo.res"; /* nom précédé de sa longueur */
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
static uint8_t res(uint8_t f) { /* appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(38, f);
return ControlPort.error;
}
static uint8_t ouvrir(const char *nom) { /* 38,1 Open Resource File, sur le canal de fichier 1 */
libre();
ControlPort.params[0] = 1;
p16(1, (uint16_t)nom);
return res(1);
}
static void fermer(void) { /* 38,2 Close Resource File */
libre();
res(2);
}
int main(void) {
uint8_t i;
uint16_t t[3];
ouvrir(demo);
for (i = 0; i < 3; i++) {
libre();
ControlPort.params[0] = i + 1;
res(6); /* Get Resource Size : 32 bits en P1-P4 */
t[i] = ControlPort.params[1] | ControlPort.params[2] << 8;
}
fermer();
printf("Tailles : %u, %u, %u octets\n", t[0], t[1], t[2]);
return 0;
}Tailles : 7, 17, 9 octetsMad Pascal
// Lire la taille d'une ressource (groupe 38, fonction 6, Trinity).
program rs6;
uses crt, neo6502;
// demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
// caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
const demo: array[0..8] of byte = (8, ord('d'), ord('e'), ord('m'), ord('o'), ord('.'), ord('r'), ord('e'), ord('s'));
function res(f: byte): byte; // appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(38, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function ouvrir(nom: pointer): byte; // 38,1 Open Resource File, sur le canal de fichier 1
begin
NeoWaitMessage;
NeoMessage.params[0] := 1;
NeoMessage.params[1] := lo(word(nom));
NeoMessage.params[2] := hi(word(nom));
result := res(1);
end;
procedure fermer; // 38,2 Close Resource File
begin
NeoWaitMessage;
res(2);
end;
var i: byte;
t: array[0..2] of word;
begin
ouvrir(@demo);
for i := 0 to 2 do begin
NeoWaitMessage;
NeoMessage.params[0] := i + 1;
res(6); // Get Resource Size : 32 bits en P1-P4
t[i] := NeoMessage.params[1] + NeoMessage.params[2] shl 8;
end;
fermer;
writeln('Tailles : ', t[0], ', ', t[1], ', ', t[2], ' octets');
end.Tailles : 7, 17, 9 octetsNeoBASIC
10 ' Lire la taille d'une ressource (groupe 38, fonction 6, Trinity)
15 ' demo.res (fabrique avec tools/toolbox/mkres.py de Trinity) : TEXT 1, FONT 1, TEXT 2
20 s$ = "demo.res" : gosub 8900 : gosub 8000
30 dim t(2)
40 for k = 0 to 2
50 while peek($ff00) : wend : poke $ff04, k + 1 : f = 6 : gosub 8110 : ' Get Resource Size : 32 bits en P1-P4
60 t(k) = deek($ff05) : next k
70 gosub 8200
80 print "Tailles : ";t(0);", ";t(1);", ";t(2);" octets"
90 end
8000 ' 38,1 Open Resource File sur le canal 1 : nom precede de sa longueur en nm ; erreur dans e
8010 while peek($ff00) : wend : poke $ff04, 1 : doke $ff05, nm : f = 1
8100 ' appel 38,f, parametres deja poses ; erreur dans e
8110 poke $ff01, f : poke $ff00, 38
8120 while peek($ff00) : wend : e = peek($ff02) : return
8200 ' 38,2 Close Resource File
8210 while peek($ff00) : wend : f = 2 : goto 8110
8900 ' chaine s$ precedee de sa longueur, dans un bloc neuf nm
8910 nm = alloc(len(s$) + 1) : poke nm, len(s$) : for i = 1 to len(s$) : poke nm + i, asc(mid$(s$, i, 1)) : next i : returnTailles : 7, 17, 9 octetsAssembleur 65C02 (64tass)
; Lire la taille d'une ressource (groupe 38, fonction 6, 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: lda #<demo
ldx #>demo
jsr ouvrir
ldx #0
_r: phx
jsr WaitMessage
pla
pha
lsr a
inc a
sta ControlPort+4 ; ressource 1, 2, 3
ldx #6 ; Get Resource Size : 32 bits en P1-P4
jsr res
plx
lda ControlPort+5
sta t,x
lda ControlPort+6
sta t+1,x
inx
inx
cpx #6
bne _r
jsr WaitMessage
ldx #2 ; 38,2 Close Resource File
jsr res
lda #<t0
ldx #>t0
jsr ecrire
lda t
ldx t+1
jsr dec16
lda #<t1
ldx #>t1
jsr ecrire
lda t+2
ldx t+2+1
jsr dec16
lda #<t2
ldx #>t2
jsr ecrire
lda t+4
ldx t+4+1
jsr dec16
lda #<t3
ldx #>t3
jsr ecrire
lda #13
jsr WriteCharacter
rts
; demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
; caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
demo: .byte 8
.text "demo.res" ; nom précédé de sa longueur
t: .fill 6 ; 3 tailles sur 16 bits
t0: .text "Tailles : ", 0
t1: .text ", ", 0
t2: .text ", ", 0
t3: .text " octets", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
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
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; 38,1 Open Resource File, sur le canal de fichier 1 : nom en A (poids faible) et X (poids fort) ; erreur dans A.
ouvrir: pha
phx
jsr WaitMessage
lda #1
sta ControlPort+4
plx
stx ControlPort+6
pla
sta ControlPort+5
ldx #1
; Appel 38,X (paramètres déjà posés) ; rend l'indicateur d'erreur dans A.
res: lda #38
jsr appel
lda ControlPort+2
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
blk = $82
diviseur: .byte 0
fin: .byte 0Tailles : 7, 17, 9 octets38,7 Load Resource Trinity
Copie une ressource dans une page de mémoire (pages de 12,2).
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro de la ressource (1 à n, dans l'ordre de la table) |
P1 | uint8 | page : $00 RAM du 6502, $80 et $81 mémoire vidéo, $90 mémoire graphique |
P2-P3 | addr | adresse dans la page |
P4-P5 | uint16 | nombre d'octets au plus |
| Octets | Type | Rôle |
|---|---|---|
P6-P7 | uint16 | nombre d'octets lus (toute la ressource si elle tient) |
erreur | uint8 | 1 si la zone sort de la page |
Avec un maximum de 4 octets, seul le début de la ressource est lu : « Bonj ». NeoBASIC n'a pas de mot-clé pour cet appel.
Texte de la documentation du firmware (anglais)
Reads resource Parameter:0 into memory page Parameter:1 ($00 6502 RAM, $80/$81 video RAM, $90 graphics RAM ; pages of Function 12,2) at address Parameters:2,3, at most Parameters:4,5 bytes ; Parameters:6,7 receive the number of bytes read (the whole resource when it fits). Error 1 if the range leaves the page.
C (llvm-mos)
/* Charger une ressource en mémoire (groupe 38, fonction 7, 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)
;
}
/* demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ». */
static const char demo[] = "\010demo.res"; /* nom précédé de sa longueur */
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
static uint8_t res(uint8_t f) { /* appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(38, f);
return ControlPort.error;
}
static uint8_t ouvrir(const char *nom) { /* 38,1 Open Resource File, sur le canal de fichier 1 */
libre();
ControlPort.params[0] = 1;
p16(1, (uint16_t)nom);
return res(1);
}
static void fermer(void) { /* 38,2 Close Resource File */
libre();
res(2);
}
static char tampon[16];
static uint16_t charger(uint8_t r, uint16_t max) { /* Load Resource : page $00 (RAM du 6502), adresse, max */
libre();
ControlPort.params[0] = r;
ControlPort.params[1] = 0;
p16(2, (uint16_t)tampon);
p16(4, max);
res(7);
return ControlPort.params[6] | ControlPort.params[7] << 8; /* octets lus */
}
int main(void) {
uint16_t n1, n2;
uint8_t i;
ouvrir(demo);
n1 = charger(3, sizeof tampon); /* TEXT 2 en entier */
printf("TEXT 2 : %u octets, ", n1);
for (i = 0; i < n1; i++)
putchar(tampon[i]);
n2 = charger(1, 4); /* TEXT 1, 4 octets au plus */
fermer();
printf("\nTEXT 1, 4 au plus : %u octets, ", n2);
for (i = 0; i < n2; i++)
putchar(tampon[i]);
putchar('\n');
return 0;
}TEXT 2 : 9 octets, Neo6502 !
TEXT 1, 4 au plus : 4 octets, BonjMad Pascal
// Charger une ressource en mémoire (groupe 38, fonction 7, Trinity).
program rs7;
uses crt, neo6502;
// demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
// caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
const demo: array[0..8] of byte = (8, ord('d'), ord('e'), ord('m'), ord('o'), ord('.'), ord('r'), ord('e'), ord('s'));
function res(f: byte): byte; // appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(38, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function ouvrir(nom: pointer): byte; // 38,1 Open Resource File, sur le canal de fichier 1
begin
NeoWaitMessage;
NeoMessage.params[0] := 1;
NeoMessage.params[1] := lo(word(nom));
NeoMessage.params[2] := hi(word(nom));
result := res(1);
end;
procedure fermer; // 38,2 Close Resource File
begin
NeoWaitMessage;
res(2);
end;
var tampon: array[0..15] of byte;
function charger(r: byte; max: word): word; // Load Resource : page $00 (RAM du 6502), adresse, max
begin
NeoWaitMessage;
NeoMessage.params[0] := r;
NeoMessage.params[1] := 0;
NeoMessage.params[2] := lo(word(@tampon));
NeoMessage.params[3] := hi(word(@tampon));
NeoMessage.params[4] := lo(max);
NeoMessage.params[5] := hi(max);
res(7);
result := NeoMessage.params[6] + NeoMessage.params[7] shl 8; // octets lus
end;
var n1, n2, i: word;
begin
ouvrir(@demo);
n1 := charger(3, 16); // TEXT 2 en entier
write('TEXT 2 : ', n1, ' octets, ');
for i := 0 to n1 - 1 do write(chr(tampon[i]));
writeln;
n2 := charger(1, 4); // TEXT 1, 4 octets au plus
fermer;
write('TEXT 1, 4 au plus : ', n2, ' octets, ');
for i := 0 to n2 - 1 do write(chr(tampon[i]));
writeln;
end.TEXT 2 : 9 octets, Neo6502 !
TEXT 1, 4 au plus : 4 octets, BonjNeoBASIC
10 ' Charger une ressource en memoire (groupe 38, fonction 7, Trinity)
15 ' demo.res (fabrique avec tools/toolbox/mkres.py de Trinity) : TEXT 1, FONT 1, TEXT 2
20 tp = alloc(16)
30 s$ = "demo.res" : gosub 8900 : gosub 8000
40 r = 3 : mx = 16 : gosub 2000 : n1 = lu : ' TEXT 2 en entier
50 print "TEXT 2 : ";n1;" octets, "; : gosub 3000
60 r = 1 : mx = 4 : gosub 2000 : n2 = lu : ' TEXT 1, 4 octets au plus
70 gosub 8200
80 print "TEXT 1, 4 au plus : ";n2;" octets, "; : gosub 3000
90 end
2000 ' Load Resource : ressource r, page $00 (RAM du 6502), adresse tp, mx octets au plus ; octets lus dans lu
2010 while peek($ff00) : wend : poke $ff04, r : poke $ff05, 0 : doke $ff06, tp : doke $ff08, mx
2020 f = 7 : gosub 8110 : lu = deek($ff0a) : return
3000 for i = 0 to lu - 1 : print chr$(peek(tp + i)); : next i : print : return
8000 ' 38,1 Open Resource File sur le canal 1 : nom precede de sa longueur en nm ; erreur dans e
8010 while peek($ff00) : wend : poke $ff04, 1 : doke $ff05, nm : f = 1
8100 ' appel 38,f, parametres deja poses ; erreur dans e
8110 poke $ff01, f : poke $ff00, 38
8120 while peek($ff00) : wend : e = peek($ff02) : return
8200 ' 38,2 Close Resource File
8210 while peek($ff00) : wend : f = 2 : goto 8110
8900 ' chaine s$ precedee de sa longueur, dans un bloc neuf nm
8910 nm = alloc(len(s$) + 1) : poke nm, len(s$) : for i = 1 to len(s$) : poke nm + i, asc(mid$(s$, i, 1)) : next i : returnTEXT 2 : 9 octets, Neo6502 !
TEXT 1, 4 au plus : 4 octets, BonjAssembleur 65C02 (64tass)
; Charger une ressource en mémoire (groupe 38, fonction 7, 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: lda #<demo
ldx #>demo
jsr ouvrir
lda #<b0
ldx #>b0
jsr envoi
lda ControlPort+10 ; P6-P7 : octets lus
sta n1
lda ControlPort+11
sta n1+1
lda #<t1
ldx #>t1
jsr ecrire
lda n1
ldx n1+1
jsr dec16
lda #<t2
ldx #>t2
jsr ecrire
ldx #0
_m1: cpx n1
beq _f1
lda tampon,x
jsr WriteCharacter
inx
bra _m1
_f1: lda #13
jsr WriteCharacter
lda #<b3
ldx #>b3
jsr envoi
lda ControlPort+10 ; P6-P7 : octets lus
sta n2
lda ControlPort+11
sta n2+1
jsr WaitMessage
ldx #2 ; 38,2 Close Resource File
jsr res
lda #<t4
ldx #>t4
jsr ecrire
lda n2
ldx n2+1
jsr dec16
lda #<t5
ldx #>t5
jsr ecrire
ldx #0
_m2: cpx n2
beq _f2
lda tampon,x
jsr WriteCharacter
inx
bra _m2
_f2: lda #13
jsr WriteCharacter
rts
; demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
; caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
demo: .byte 8
.text "demo.res" ; nom précédé de sa longueur
tampon: .fill 16
b0: .byte 38, 7, 6, 3, 0 ; Load Resource : TEXT 2 en entier, page $00 (RAM du 6502)
.word tampon, 16
n1: .fill 2
t1: .text "TEXT 2 : ", 0
t2: .text " octets, ", 0
b3: .byte 38, 7, 6, 1, 0 ; TEXT 1, 4 octets au plus
.word tampon, 4
n2: .fill 2
t4: .text "TEXT 1, 4 au plus : ", 0
t5: .text " octets, ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
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
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; 38,1 Open Resource File, sur le canal de fichier 1 : nom en A (poids faible) et X (poids fort) ; erreur dans A.
ouvrir: pha
phx
jsr WaitMessage
lda #1
sta ControlPort+4
plx
stx ControlPort+6
pla
sta ControlPort+5
ldx #1
; Appel 38,X (paramètres déjà posés) ; rend l'indicateur d'erreur dans A.
res: lda #38
jsr appel
lda ControlPort+2
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
blk = $82
diviseur: .byte 0
fin: .byte 0TEXT 2 : 9 octets, Neo6502 !
TEXT 1, 4 au plus : 4 octets, Bonj38,8 Use Font Trinity
Charge une ressource (comme 38,7) puis en fait la police de QuickDraw (32,15).
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | numéro de la ressource (1 à n, dans l'ordre de la table) |
P1 | uint8 | page : $00 RAM du 6502, $80 et $81 mémoire vidéo, $90 mémoire graphique |
P2-P3 | addr | adresse dans la page |
P4-P5 | uint16 | nombre d'octets au plus |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | 1 si la ressource n'est pas une police NF1 valide |
La police est lue sur place à chaque dessin (voir 32,15) : la zone où elle est chargée doit rester intacte. L'exemple charge la police d'un caractère de demo.res et écrit « A » avec 32,16 : un cadre 8 × 8, coin allumé, milieu éteint. NeoBASIC n'a pas de mot-clé pour cet appel.
Texte de la documentation du firmware (anglais)
Load Resource (same parameters) followed by Function 32,15 Set Font on the loaded NF1 font : the resource becomes the QuickDraw font (error 1 if it is not a valid font).
C (llvm-mos)
/* Charger une police depuis les ressources (groupe 38, fonction 8, 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)
;
}
/* demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ». */
static const char demo[] = "\010demo.res"; /* nom précédé de sa longueur */
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
static uint8_t res(uint8_t f) { /* appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(38, f);
return ControlPort.error;
}
static uint8_t ouvrir(const char *nom) { /* 38,1 Open Resource File, sur le canal de fichier 1 */
libre();
ControlPort.params[0] = 1;
p16(1, (uint16_t)nom);
return res(1);
}
static void fermer(void) { /* 38,2 Close Resource File */
libre();
res(2);
}
static uint8_t police[32]; /* la police est lue sur place : elle doit rester en mémoire */
static const char texte[] = "\001A";
static uint8_t pixel(int16_t x, int16_t y) { /* 5,33 : couleur du fond en (x, y) */
libre(); p16(0, x); p16(2, y); api(5, 33);
return ControlPort.params[0];
}
static uint8_t utiliser(uint8_t r) { /* Use Font : Load Resource puis 32,15 Set Font */
libre();
ControlPort.params[0] = r;
ControlPort.params[1] = 0;
p16(2, (uint16_t)police);
p16(4, sizeof police);
return res(8);
}
int main(void) {
uint8_t e1, e2, coin, milieu;
putchar(12); /* écran effacé : on relit des pixels */
libre(); api(32, 1); /* 32,1 Init Graf */
ouvrir(demo);
e1 = utiliser(2); /* FONT 1 */
libre(); ControlPort.params[0] = 6; api(32, 4);
libre(); p16(0, 100); p16(2, 100); api(32, 5);
libre(); p16(0, (uint16_t)texte); api(32, 16); /* 32,16 : « A », un cadre 8 × 8 */
coin = pixel(100, 100);
milieu = pixel(104, 104);
e2 = utiliser(1); /* TEXT 1 : pas une police */
fermer();
libre(); api(32, 1); /* police intégrée */
printf("Police : erreur %u, coin %u, milieu %u\nTEXT 1 : erreur %u\n", e1, coin, milieu, e2);
return 0;
}Police : erreur 0, coin 6, milieu 0
TEXT 1 : erreur 1Mad Pascal
// Charger une police depuis les ressources (groupe 38, fonction 8, Trinity).
program rs8;
uses crt, neo6502;
// demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
// caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
const demo: array[0..8] of byte = (8, ord('d'), ord('e'), ord('m'), ord('o'), ord('.'), ord('r'), ord('e'), ord('s'));
function res(f: byte): byte; // appel 38,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(38, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function ouvrir(nom: pointer): byte; // 38,1 Open Resource File, sur le canal de fichier 1
begin
NeoWaitMessage;
NeoMessage.params[0] := 1;
NeoMessage.params[1] := lo(word(nom));
NeoMessage.params[2] := hi(word(nom));
result := res(1);
end;
procedure fermer; // 38,2 Close Resource File
begin
NeoWaitMessage;
res(2);
end;
const texte: array[0..1] of byte = (1, ord('A'));
var police: array[0..31] of byte; // la police est lue sur place : elle doit rester en mémoire
e1, e2, coin, milieu: byte;
function utiliser(r: byte): byte; // Use Font : Load Resource puis 32,15 Set Font
begin
NeoWaitMessage;
NeoMessage.params[0] := r;
NeoMessage.params[1] := 0;
NeoMessage.params[2] := lo(word(@police));
NeoMessage.params[3] := hi(word(@police));
NeoMessage.params[4] := 32;
NeoMessage.params[5] := 0;
result := res(8);
end;
begin
write(chr(12)); // écran effacé : on relit des pixels
NeoWaitMessage; NeoSendMessage(32, 1); NeoWaitMessage; // 32,1 Init Graf
ouvrir(@demo);
e1 := utiliser(2); // FONT 1
NeoMessage.params[0] := 6; NeoSendMessage(32, 4); NeoWaitMessage;
wordParams[0] := 100; wordParams[1] := 100; NeoSendMessage(32, 5); NeoWaitMessage;
wordParams[0] := word(@texte); NeoSendMessage(32, 16); NeoWaitMessage; // 32,16 : « A », un cadre 8 × 8
coin := NeoGetPixel(100, 100);
milieu := NeoGetPixel(104, 104);
e2 := utiliser(1); // TEXT 1 : pas une police
fermer;
NeoSendMessage(32, 1); NeoWaitMessage; // police intégrée
writeln('Police : erreur ', e1, ', coin ', coin, ', milieu ', milieu);
writeln('TEXT 1 : erreur ', e2);
end.Police : erreur 0, coin 6, milieu 0
TEXT 1 : erreur 1NeoBASIC
10 ' Charger une police depuis les ressources (groupe 38, fonction 8, Trinity)
15 ' demo.res (fabrique avec tools/toolbox/mkres.py de Trinity) : TEXT 1, FONT 1, TEXT 2
20 cls : ' ecran efface : on relit des pixels
30 po = alloc(32) : ' la police est lue sur place : elle doit rester en memoire
40 tx = alloc(2) : poke tx, 1 : poke tx + 1, asc("A")
50 while peek($ff00) : wend : poke $ff01, 1 : poke $ff00, 32 : ' 32,1 Init Graf
60 s$ = "demo.res" : gosub 8900 : gosub 8000
70 r = 2 : gosub 2000 : e1 = e : ' FONT 1
80 while peek($ff00) : wend : poke $ff04, 6 : poke $ff01, 4 : poke $ff00, 32
90 while peek($ff00) : wend : doke $ff04, 100 : doke $ff06, 100 : poke $ff01, 5 : poke $ff00, 32
100 while peek($ff00) : wend : doke $ff04, tx : poke $ff01, 16 : poke $ff00, 32 : ' 32,16 : « A », un cadre 8 x 8
110 while peek($ff00) : wend : co = point(100, 100) : mi = point(104, 104)
120 r = 1 : gosub 2000 : e2 = e : ' TEXT 1 : pas une police
130 gosub 8200
140 while peek($ff00) : wend : poke $ff01, 1 : poke $ff00, 32 : ' police integree
150 while peek($ff00) : wend
160 print "Police : erreur ";e1;", coin ";co;", milieu ";mi
170 print "TEXT 1 : erreur ";e2
180 end
2000 ' Use Font : Load Resource de r dans po (32 octets au plus) puis 32,15 Set Font
2010 while peek($ff00) : wend : poke $ff04, r : poke $ff05, 0 : doke $ff06, po : doke $ff08, 32 : f = 8 : goto 8110
8000 ' 38,1 Open Resource File sur le canal 1 : nom precede de sa longueur en nm ; erreur dans e
8010 while peek($ff00) : wend : poke $ff04, 1 : doke $ff05, nm : f = 1
8100 ' appel 38,f, parametres deja poses ; erreur dans e
8110 poke $ff01, f : poke $ff00, 38
8120 while peek($ff00) : wend : e = peek($ff02) : return
8200 ' 38,2 Close Resource File
8210 while peek($ff00) : wend : f = 2 : goto 8110
8900 ' chaine s$ precedee de sa longueur, dans un bloc neuf nm
8910 nm = alloc(len(s$) + 1) : poke nm, len(s$) : for i = 1 to len(s$) : poke nm + i, asc(mid$(s$, i, 1)) : next i : returnPolice : erreur 0, coin 6, milieu 0
TEXT 1 : erreur 1Assembleur 65C02 (64tass)
; Charger une police depuis les ressources (groupe 38, fonction 8, 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: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #<demo
ldx #>demo
jsr ouvrir
lda #<b1
ldx #>b1
jsr envoi
lda ControlPort+2
sta e1
lda #<b2
ldx #>b2
jsr envoi
lda #<b3
ldx #>b3
jsr envoi
lda #<b4
ldx #>b4
jsr envoi
lda #100
ldy #100
jsr pixel
sta co
lda #104
ldy #104
jsr pixel
sta mi
lda #<b5
ldx #>b5
jsr envoi
lda ControlPort+2
sta e2
jsr WaitMessage
ldx #2 ; 38,2 Close Resource File
jsr res
lda #<b6
ldx #>b6
jsr envoi
lda #<t7
ldx #>t7
jsr ecrire
lda e1
jsr decimal
lda #<t8
ldx #>t8
jsr ecrire
lda co
jsr decimal
lda #<t9
ldx #>t9
jsr ecrire
lda mi
jsr decimal
lda #13
jsr WriteCharacter
lda #<t10
ldx #>t10
jsr ecrire
lda e2
jsr decimal
lda #13
jsr WriteCharacter
rts
; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : X
stz ControlPort+5
sty ControlPort+6 ; P2-P3 : Y
stz ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; demo.res (fabriqué avec tools/toolbox/mkres.py de Trinity) : TEXT 1 « Bonjour », FONT 1 (police NF1 d'un
; caractère, un cadre 8 × 8), TEXT 2 « Neo6502 ! ».
demo: .byte 8
.text "demo.res" ; nom précédé de sa longueur
police: .fill 32 ; la police est lue sur place : elle doit rester en mémoire
texte: .byte 1
.text "A"
b0: .byte 32, 1, 0 ; 32,1 Init Graf
b1: .byte 38, 8, 6, 2, 0 ; Use Font : FONT 1, puis 32,15 Set Font
.word police, 32
e1: .byte 0
b2: .byte 32, 4, 1, 6 ; 32,4 : couleur 6
b3: .byte 32, 5, 4 ; 32,5
.word 100, 100
b4: .byte 32, 16, 2 ; 32,16 : « A », un cadre 8 × 8
.word texte
co: .byte 0
mi: .byte 0
b5: .byte 38, 8, 6, 1, 0 ; TEXT 1 : pas une police
.word police, 32
e2: .byte 0
b6: .byte 32, 1, 0 ; police intégrée
t7: .text "Police : erreur ", 0
t8: .text ", coin ", 0
t9: .text ", milieu ", 0
t10: .text "TEXT 1 : erreur ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
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
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; 38,1 Open Resource File, sur le canal de fichier 1 : nom en A (poids faible) et X (poids fort) ; erreur dans A.
ouvrir: pha
phx
jsr WaitMessage
lda #1
sta ControlPort+4
plx
stx ControlPort+6
pla
sta ControlPort+5
ldx #1
; Appel 38,X (paramètres déjà posés) ; rend l'indicateur d'erreur dans A.
res: lda #38
jsr appel
lda ControlPort+2
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
blk = $82
diviseur: .byte 0
fin: .byte 0Police : erreur 0, coin 6, milieu 0
TEXT 1 : erreur 1