Group 38 — Resource Manager 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
The resource manager of the Trinity toolbox reads resource files in the NR1 format: a header ("NR", version 1, number of resources), a table of 16 bytes per resource (4-character type, 16-bit id, 32-bit offset and size), then the data. They are built with tools/toolbox/mkres.py, in the Trinity repository.
The examples use demo.res, put at the root of the storage and built as follows: mkres.py demo.res TEXT:1:bonjour.txt FONT:1:cadre.nf1 TEXT:2:neo.txt, where bonjour.txt holds "Bonjour", neo.txt "Neo6502 !" and cadre.nf1 the one-character font of example 32,15 (17 bytes). The examples open it on file channel 1.
38,1 Open Resource File Trinity
Opens an NR1 resource file on a file channel.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | file channel |
P1-P2 | addr | address of the name, preceded by its length |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | 1 bad channel or not a resource file, 2 storage error |
One resource file is open at a time: opening another closes the first. Nothing is cached on the RP2040 side: the table is read from storage on each call. On the bench, a missing file returns error 2. NeoBASIC has no keyword for this call.
Firmware documentation text
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 ressources65C02 assembly (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
Closes the resource file and its channel.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | 1 if no file is open |
After closing, the other functions of the group return error 1. NeoBASIC has no keyword for this call.
Firmware documentation text
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 165C02 assembly (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
Returns the number of resources of the open file.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | number of resources |
Resources are numbered from 1 to this number, in table order. NeoBASIC has no keyword for this call.
Firmware documentation text
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 : 365C02 assembly (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
Looks for a resource by its type and id.
| Bytes | Type | Meaning |
|---|---|---|
P0-P3 | uint8 | type: 4 ASCII characters, padded with spaces |
P4-P5 | uint16 | id |
| Bytes | Type | Meaning |
|---|---|---|
P6 | uint8 | resource number (0 if not found) |
erreur | uint8 | 3 if the resource is not found |
NeoBASIC has no keyword for this call.
Firmware documentation text
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)65C02 assembly (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
Returns the type and id of a resource.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | resource number (1 to n, in table order) |
| Bytes | Type | Meaning |
|---|---|---|
P1-P4 | uint8 | type (4 characters) |
P5-P6 | uint16 | id |
erreur | uint8 | 3 if the number is out of range |
With 38,3, lets the program walk the whole table. NeoBASIC has no keyword for this call.
Firmware documentation text
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 365C02 assembly (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
Returns the size of a resource in bytes.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | resource number (1 to n, in table order) |
| Bytes | Type | Meaning |
|---|---|---|
P1-P4 | uint32 | size in bytes |
NeoBASIC has no keyword for this call.
Firmware documentation text
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 octets65C02 assembly (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
Copies a resource into a memory page (pages of 12,2).
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | resource number (1 to n, in table order) |
P1 | uint8 | page: $00 6502 RAM, $80 and $81 video RAM, $90 graphics RAM |
P2-P3 | addr | address in the page |
P4-P5 | uint16 | maximum number of bytes |
| Bytes | Type | Meaning |
|---|---|---|
P6-P7 | uint16 | number of bytes read (the whole resource when it fits) |
erreur | uint8 | 1 if the range leaves the page |
With a maximum of 4 bytes, only the start of the resource is read: "Bonj". NeoBASIC has no keyword for this call.
Firmware documentation text
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, Bonj65C02 assembly (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
Loads a resource (as 38,7) then makes it the QuickDraw font (32,15).
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | resource number (1 to n, in table order) |
P1 | uint8 | page: $00 6502 RAM, $80 and $81 video RAM, $90 graphics RAM |
P2-P3 | addr | address in the page |
P4-P5 | uint16 | maximum number of bytes |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | 1 if the resource is not a valid NF1 font |
The font is read in place at each drawing (see 32,15): the area where it is loaded must stay intact. The example loads the one-character font of demo.res and writes "A" with 32,16: an 8 × 8 frame, corner set, middle clear. NeoBASIC has no keyword for this call.
Firmware documentation text
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 165C02 assembly (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