Tachibana
Language: English

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.

Inputs
BytesTypeMeaning
P0uint8file channel
P1-P2addraddress of the name, preceded by its length
Outputs
BytesTypeMeaning
erreuruint81 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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Fichier absent : erreur 2
demo.res : erreur 0, 3 ressources
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Fichier absent : erreur 2
demo.res : erreur 0, 3 ressources
NeoBASIC
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 : return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Fichier absent : erreur 2
demo.res : erreur 0, 3 ressources
65C02 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 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Fichier absent : erreur 2
demo.res : erreur 0, 3 ressources

38,2 Close Resource File Trinity

Closes the resource file and its channel.

Inputs: none.

Outputs
BytesTypeMeaning
erreuruint81 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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Fermeture : erreur 0 ; encore : erreur 1
Compter ensuite : erreur 1
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Fermeture : erreur 0 ; encore : erreur 1
Compter ensuite : erreur 1
NeoBASIC
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 : return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Fermeture : erreur 0 ; encore : erreur 1
Compter ensuite : erreur 1
65C02 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 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Fermeture : erreur 0 ; encore : erreur 1
Compter ensuite : erreur 1

38,3 Count Resources Trinity

Returns the number of resources of the open file.

Inputs: none.

Outputs
BytesTypeMeaning
P0uint8number 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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Ressources : 3
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Ressources : 3
NeoBASIC
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 : return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Ressources : 3
65C02 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 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Ressources : 3

38,4 Find Resource Trinity

Looks for a resource by its type and id.

Inputs
BytesTypeMeaning
P0-P3uint8type: 4 ASCII characters, padded with spaces
P4-P5uint16id
Outputs
BytesTypeMeaning
P6uint8resource number (0 if not found)
erreuruint83 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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
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 : return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
FONT 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 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
FONT 1 : 2, TEXT 2 : 3, TEXT 9 : 0 (erreur 3)

38,5 Get Resource Info Trinity

Returns the type and id of a resource.

Inputs
BytesTypeMeaning
P0uint8resource number (1 to n, in table order)
Outputs
BytesTypeMeaning
P1-P4uint8type (4 characters)
P5-P6uint16id
erreuruint83 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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
1 : TEXT 1
2 : FONT 1
3 : TEXT 2
4 : erreur 3
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
1 : TEXT 1
2 : FONT 1
3 : TEXT 2
4 : erreur 3
NeoBASIC
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 : return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
1 : TEXT 1
2 : FONT 1
3 : TEXT 2
4 : erreur 3
65C02 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 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
1 : TEXT 1
2 : FONT 1
3 : TEXT 2
4 : erreur 3

38,6 Get Resource Size Trinity

Returns the size of a resource in bytes.

Inputs
BytesTypeMeaning
P0uint8resource number (1 to n, in table order)
Outputs
BytesTypeMeaning
P1-P4uint32size 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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Tailles : 7, 17, 9 octets
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Tailles : 7, 17, 9 octets
NeoBASIC
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 : return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Tailles : 7, 17, 9 octets
65C02 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 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Tailles : 7, 17, 9 octets

38,7 Load Resource Trinity

Copies a resource into a memory page (pages of 12,2).

Inputs
BytesTypeMeaning
P0uint8resource number (1 to n, in table order)
P1uint8page: $00 6502 RAM, $80 and $81 video RAM, $90 graphics RAM
P2-P3addraddress in the page
P4-P5uint16maximum number of bytes
Outputs
BytesTypeMeaning
P6-P7uint16number of bytes read (the whole resource when it fits)
erreuruint81 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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
TEXT 2 : 9 octets, Neo6502 !
TEXT 1, 4 au plus : 4 octets, Bonj
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
TEXT 2 : 9 octets, Neo6502 !
TEXT 1, 4 au plus : 4 octets, Bonj
NeoBASIC
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 : return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
TEXT 2 : 9 octets, Neo6502 !
TEXT 1, 4 au plus : 4 octets, Bonj
65C02 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 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
TEXT 2 : 9 octets, Neo6502 !
TEXT 1, 4 au plus : 4 octets, Bonj

38,8 Use Font Trinity

Loads a resource (as 38,7) then makes it the QuickDraw font (32,15).

Inputs
BytesTypeMeaning
P0uint8resource number (1 to n, in table order)
P1uint8page: $00 6502 RAM, $80 and $81 video RAM, $90 graphics RAM
P2-P3addraddress in the page
P4-P5uint16maximum number of bytes
Outputs
BytesTypeMeaning
erreuruint81 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;
}
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Police : erreur 0, coin 6, milieu 0
TEXT 1 : erreur 1
Mad 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.
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Police : erreur 0, coin 6, milieu 0
TEXT 1 : erreur 1
NeoBASIC
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 : return
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Police : erreur 0, coin 6, milieu 0
TEXT 1 : erreur 1
65C02 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 0
Output observed in the Phosphoneo emulator, Trinity firmware 0.16.69:
Police : erreur 0, coin 6, milieu 0
TEXT 1 : erreur 1

← The Neo6502 API