Tachibana
Langue : français

Groupe 4 — Mathématiques Officiel

4,0 Addition · 4,1 Subtraction · 4,2 Multiplication · 4,3 Decimal Division · 4,4 Integer Division · 4,5 Integer Modulus · 4,6 Compare · 4,7 Power · 4,8 Distance (counter-rectangle) · 4,9 Angle calculation (arctangent2) · 4,16 Negate · 4,17 Floor · 4,18 Square Root · 4,19 Sine · 4,20 Cosine · 4,21 Tangent · 4,22 Arctangent · 4,23 Exponent · 4,24 Logarithm · 4,25 Absolute Value · 4,26 Sign · 4,27 Random Decimal · 4,28 Random Integer · 4,32 Number to Decimal · 4,33 String to Number · 4,34 Number to String · 4,35 Set Degree/Radian Mode

Le groupe 4 est un coprocesseur de calcul : le RP2040 calcule en entiers 32 bits ou en flottants simple précision (IEEE 754) pour le 65C02. Les nombres ne passent pas par la boîte aux lettres mais par deux registres rangés dans la mémoire du 65C02, dont chaque appel donne l'adresse.

Un registre fait 5 octets : un octet de type ($00 entier, $40 flottant), puis les 4 octets de la valeur, poids faible d'abord. P0-P1 donne l'adresse de l'octet de type du registre 1 ; celui du registre 2 est à l'octet suivant. P2 donne le pas entre deux octets d'un même registre : avec un pas de 2, les deux registres sont entrelacés sur 10 octets (types, puis octets 0 des deux valeurs, puis octets 1…). C'est la disposition des exemples, et celle de l'unité neo6502math de Mad Pascal ; NeoBASIC y range sa pile d'expressions.

Le résultat revient dans le registre 1, avec son type. Une opération à deux registres calcule en flottant dès qu'un des deux est flottant, en entier sinon. Pour afficher un résultat, les exemples le convertissent en texte avec 4,34, ce qui donne le format du firmware (6 décimales pour un flottant).

Les angles sont en degrés par défaut ; 4,35 passe en radians. Le démarrage d'un programme Mad Pascal passe en radians (code de démarrage de Mad Pascal 1.7.8) : les exemples Pascal qui utilisent des angles repassent en degrés.

4,0 Addition Officiel

Registre 1 := registre 1 + registre 2.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type) ; le registre 2 suit d'un octet
P2uint8pas entre les octets d'un registre
registre 1nombrepremier opérande
registre 2nombresecond opérande
Sorties
OctetsTypeRôle
registre 1nombresomme (flottant si un opérande l'est)

Unité neo6502math de Mad Pascal (version 0.30.0) : SetMathStack(v, 0) écrit aussi la position 1 (le code de la position 0 continue sur celui de la position 1). Il faut donc donner la position 0 avant la position 1 ; dans l'autre ordre, les deux registres valent le premier nombre (vérifié : 7 \ 2 donne alors 1). En NeoBASIC, + passe par cet appel pour les flottants ; deux entiers sont additionnés par le 65C02.

Texte de la documentation du firmware (anglais)

Register1 := Register 1 + Register2

C (llvm-mos)
/* Additionner deux nombres (groupe 4, fonction 0). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    flottant(1, 1.5f);                          /* registre 1 */
    flottant(2, 2.25f);                         /* registre 2 */
    calcul(0);                                      /* Addition */
    printf("1.5 + 2.25 = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
1.5 + 2.25 = 3.750000
Mad Pascal
// Additionner deux nombres (groupe 4, fonction 0).
program calcul0;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: float;
    b: float;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := 1.5;
  b := 2.25;
  SetMathStack(a, 0);                          // position 0 d'abord (voir 4,0)
  SetMathStack(b, 1);
  calcul(0);                                 // Addition
  writeln('1.5 + 2.25 = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
1.5 + 2.25 = 3.750000
NeoBASIC
10 ' Additionner deux nombres (groupe 4, fonction 0)
20 print "1.5 + 2.25 = ";1.5 + 2.25
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
1.5 + 2.25 = 3.750000
Assembleur 65C02 (64tass)
; Additionner deux nombres (groupe 4, fonction 0).
        .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:  ldx #0                  ; fonction 0 : Addition
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $40, $40, $00, $00, $00, $00, $C0, $10, $3F, $40
        ; registre 1 : 1.5 (flottant), registre 2 : 2.25 (flottant) (types, puis octets entrelacés)
m:      .text "1.5 + 2.25 = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
1.5 + 2.25 = 3.750000

4,1 Subtraction Officiel

Registre 1 := registre 1 − registre 2.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type) ; le registre 2 suit d'un octet
P2uint8pas entre les octets d'un registre
registre 1nombrepremier opérande
registre 2nombresecond opérande
Sorties
OctetsTypeRôle
registre 1nombredifférence

Un entier et un flottant : le calcul se fait en flottant. En NeoBASIC, - passe par cet appel pour les flottants.

Texte de la documentation du firmware (anglais)

Register1 := Register 1 - Register2

C (llvm-mos)
/* Soustraire deux nombres (groupe 4, fonction 1). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 10);                              /* registre 1 */
    flottant(2, 25.5f);                         /* registre 2 */
    calcul(1);                                      /* Subtraction */
    printf("10 - 25.5 = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
10 - 25.5 = -15.500000
Mad Pascal
// Soustraire deux nombres (groupe 4, fonction 1).
program calcul1;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;
    b: float;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := 10;
  b := 25.5;
  SetMathStack(a, 0);                          // position 0 d'abord (voir 4,0)
  SetMathStack(b, 1);
  calcul(1);                                 // Subtraction
  writeln('10 - 25.5 = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
10 - 25.5 = -15.500000
NeoBASIC
10 ' Soustraire deux nombres (groupe 4, fonction 1)
20 print "10 - 25.5 = ";10 - 25.5
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
10 - 25.5 = -15.500000
Assembleur 65C02 (64tass)
; Soustraire deux nombres (groupe 4, fonction 1).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  ldx #1                  ; fonction 1 : Subtraction
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $40, $0A, $00, $00, $00, $00, $CC, $00, $41
        ; registre 1 : 10 (entier), registre 2 : 25.5 (flottant) (types, puis octets entrelacés)
m:      .text "10 - 25.5 = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
10 - 25.5 = -15.500000

4,2 Multiplication Officiel

Registre 1 := registre 1 × registre 2.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type) ; le registre 2 suit d'un octet
P2uint8pas entre les octets d'un registre
registre 1nombrepremier opérande
registre 2nombresecond opérande
Sorties
OctetsTypeRôle
registre 1nombreproduit (entier si les deux opérandes le sont)

Deux entiers donnent un entier 32 bits (sans contrôle de dépassement). En NeoBASIC, * passe toujours par cet appel.

Texte de la documentation du firmware (anglais)

Register1 := Register 1 * Register2

C (llvm-mos)
/* Multiplier deux entiers (groupe 4, fonction 2). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 6);                               /* registre 1 */
    entier(2, 7);                               /* registre 2 */
    calcul(2);                                      /* Multiplication */
    printf("6 * 7 = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
6 * 7 = 42
Mad Pascal
// Multiplier deux entiers (groupe 4, fonction 2).
program calcul2;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;
    b: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := 6;
  b := 7;
  SetMathStack(a, 0);                          // position 0 d'abord (voir 4,0)
  SetMathStack(b, 1);
  calcul(2);                                 // Multiplication
  writeln('6 * 7 = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
6 * 7 = 42
NeoBASIC
10 ' Multiplier deux entiers (groupe 4, fonction 2)
20 print "6 * 7 = ";6 * 7
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
6 * 7 = 42
Assembleur 65C02 (64tass)
; Multiplier deux entiers (groupe 4, fonction 2).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  ldx #2                  ; fonction 2 : Multiplication
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $06, $07, $00, $00, $00, $00, $00, $00
        ; registre 1 : 6 (entier), registre 2 : 7 (entier) (types, puis octets entrelacés)
m:      .text "6 * 7 = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
6 * 7 = 42

4,3 Decimal Division Officiel

Registre 1 := registre 1 / registre 2, toujours en flottant.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type) ; le registre 2 suit d'un octet
P2uint8pas entre les octets d'un registre
registre 1nombrepremier opérande
registre 2nombresecond opérande
Sorties
OctetsTypeRôle
registre 1nombrequotient (flottant)
erreuruint81 si le registre 2 vaut 0

Même avec deux entiers, le résultat est flottant. En NeoBASIC, / fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := Register 1 / Register2 (floating point)

C (llvm-mos)
/* Diviser en flottant (groupe 4, fonction 3). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 7);                               /* registre 1 */
    entier(2, 2);                               /* registre 2 */
    calcul(3);                                      /* Decimal Division */
    printf("7 / 2 = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
7 / 2 = 3.500000
Mad Pascal
// Diviser en flottant (groupe 4, fonction 3).
program calcul3;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;
    b: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := 7;
  b := 2;
  SetMathStack(a, 0);                          // position 0 d'abord (voir 4,0)
  SetMathStack(b, 1);
  calcul(3);                                 // Decimal Division
  writeln('7 / 2 = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
7 / 2 = 3.500000
NeoBASIC
10 ' Diviser en flottant (groupe 4, fonction 3)
20 print "7 / 2 = ";7 / 2
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
7 / 2 = 3.500000
Assembleur 65C02 (64tass)
; Diviser en flottant (groupe 4, fonction 3).
        .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:  ldx #3                  ; fonction 3 : Decimal Division
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $07, $02, $00, $00, $00, $00, $00, $00
        ; registre 1 : 7 (entier), registre 2 : 2 (entier) (types, puis octets entrelacés)
m:      .text "7 / 2 = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
7 / 2 = 3.500000

4,4 Integer Division Officiel

Registre 1 := registre 1 / registre 2, en entier (quotient tronqué).

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type) ; le registre 2 suit d'un octet
P2uint8pas entre les octets d'un registre
registre 1nombrepremier opérande
registre 2nombresecond opérande
Sorties
OctetsTypeRôle
registre 1nombrequotient entier
erreuruint81 si le registre 2 vaut 0

Des flottants sont d'abord convertis en entiers. En NeoBASIC, \ fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := Register 1 / Register2 (integer result)

C (llvm-mos)
/* Diviser en entier (groupe 4, fonction 4). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 7);                               /* registre 1 */
    entier(2, 2);                               /* registre 2 */
    calcul(4);                                      /* Integer Division */
    printf("7 \\ 2 = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
7 \ 2 = 3
Mad Pascal
// Diviser en entier (groupe 4, fonction 4).
program calcul4;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;
    b: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := 7;
  b := 2;
  SetMathStack(a, 0);                          // position 0 d'abord (voir 4,0)
  SetMathStack(b, 1);
  calcul(4);                                 // Integer Division
  writeln('7 \ 2 = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
7 \ 2 = 3
NeoBASIC
10 ' Diviser en entier (groupe 4, fonction 4)
20 print "7 \ 2 = ";7 \ 2
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
7 \ 2 = 3
Assembleur 65C02 (64tass)
; Diviser en entier (groupe 4, fonction 4).
        .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:  ldx #4                  ; fonction 4 : Integer Division
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $07, $02, $00, $00, $00, $00, $00, $00
        ; registre 1 : 7 (entier), registre 2 : 2 (entier) (types, puis octets entrelacés)
m:      .text "7 \ 2 = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
7 \ 2 = 3

4,5 Integer Modulus Officiel

Registre 1 := reste de la division entière de registre 1 par registre 2, calculé sur les valeurs absolues.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type) ; le registre 2 suit d'un octet
P2uint8pas entre les octets d'un registre
registre 1nombrepremier opérande
registre 2nombresecond opérande
Sorties
OctetsTypeRôle
registre 1nombrereste (toujours positif ou nul)
erreuruint81 si le registre 2 vaut 0

Le firmware prend les valeurs absolues des deux opérandes : -17 % 5 donne 2 (et non -2 comme en C). En NeoBASIC, % fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := Register 1 mod Register2

C (llvm-mos)
/* Reste d'une division entière (groupe 4, fonction 5). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, -17);                             /* registre 1 */
    entier(2, 5);                               /* registre 2 */
    calcul(5);                                      /* Integer Modulus */
    printf("-17 %% 5 = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
-17 % 5 = 2
Mad Pascal
// Reste d'une division entière (groupe 4, fonction 5).
program calcul5;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;
    b: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := -17;
  b := 5;
  SetMathStack(a, 0);                          // position 0 d'abord (voir 4,0)
  SetMathStack(b, 1);
  calcul(5);                                 // Integer Modulus
  writeln('-17 % 5 = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
-17 % 5 = 2
NeoBASIC
10 ' Reste d'une division entiere (groupe 4, fonction 5)
20 n = -17 : print "-17 % 5 = ";n % 5
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
-17 % 5 = 2
Assembleur 65C02 (64tass)
; Reste d'une division entière (groupe 4, fonction 5).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  ldx #5                  ; fonction 5 : Integer Modulus
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $EF, $05, $FF, $00, $FF, $00, $FF, $00
        ; registre 1 : -17 (entier), registre 2 : 5 (entier) (types, puis octets entrelacés)
m:      .text "-17 % 5 = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
-17 % 5 = 2

4,6 Compare Officiel

Compare registre 1 et registre 2 ; le résultat revient en P0.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type) ; le registre 2 suit d'un octet
P2uint8pas entre les octets d'un registre
registre 1nombrepremier opérande
registre 2nombresecond opérande
Sorties
OctetsTypeRôle
P0uint8$FF si registre 1 < registre 2, 0 si égaux, 1 si plus grand

Entre flottants, la comparaison est approchée : deux nombres dont l'écart est inférieur à un dix-millionième de leur taille sont égaux. En NeoBASIC, les comparaisons de flottants (<, =, >…) font cet appel ; celles d'entiers se font sur le 65C02.

Texte de la documentation du firmware (anglais)

Parameter:0 := Register 1 compare Register2 : returns $FF, 0, 1 for less equal and greater. Note: float comparison is approximate because of rounding.

C (llvm-mos)
/* Comparer deux flottants (groupe 4, fonction 6). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    flottant(1, 2.5f);                          /* registre 1 */
    flottant(2, 3.5f);                          /* registre 2 */
    calcul(6);                                  /* Compare */
    printf("compare(2.5, 3.5) = %u\n", ControlPort.params[0]);   /* $FF : plus petit */
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
compare(2.5, 3.5) = 255
Mad Pascal
// Comparer deux flottants (groupe 4, fonction 6).
program compare;
uses crt, neo6502, neo6502math;
var s: string[32];
    a, b: float;
    r: byte;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := 2.5;
  b := 3.5;
  SetMathStack(a, 0);                          // position 0 d'abord (voir 4,0)
  SetMathStack(b, 1);
  calcul(MATHCmp);                              // Compare
  r := NeoMessage.params[0];                    // $FF : plus petit
  writeln('compare(2.5, 3.5) = ', r);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
compare(2.5, 3.5) = 255
NeoBASIC
10 ' Comparer deux flottants (groupe 4, fonction 6)
20 print "2.5 < 3.5 : ";2.5 < 3.5
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
2.5 < 3.5 : -1
Assembleur 65C02 (64tass)
; Comparer deux flottants (groupe 4, fonction 6).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  ldx #6                     ; fonction 6 : Compare
        jsr calcul
        lda ControlPort+4          ; P0 : $FF, 0 ou 1
        pha
        lda #<m
        ldx #>m
        jsr ecrire
        pla
        jsr decimal
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $40, $40, $00, $00, $00, $00, $20, $60, $40, $40
        ; registre 1 : 2.5 (flottant), registre 2 : 3.5 (flottant) (types, puis octets entrelacés)
m:      .text "compare(2.5, 3.5) = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
compare(2.5, 3.5) = 255

4,7 Power Officiel

Registre 1 := registre 1 élevé à la puissance registre 2, en flottant.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type) ; le registre 2 suit d'un octet
P2uint8pas entre les octets d'un registre
registre 1nombrepremier opérande
registre 2nombresecond opérande
Sorties
OctetsTypeRôle
registre 1nombrepuissance (flottant)

Le résultat est toujours flottant. En NeoBASIC, pow(a, b) fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := Register 1 to the power of Register2 (floating point result whatever)

C (llvm-mos)
/* Élever à une puissance (groupe 4, fonction 7). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 2);                               /* registre 1 */
    entier(2, 10);                              /* registre 2 */
    calcul(7);                                      /* Power */
    printf("2 ^ 10 = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
2 ^ 10 = 1024.000000
Mad Pascal
// Élever à une puissance (groupe 4, fonction 7).
program calcul7;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;
    b: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := 2;
  b := 10;
  SetMathStack(a, 0);                          // position 0 d'abord (voir 4,0)
  SetMathStack(b, 1);
  calcul(7);                                 // Power
  writeln('2 ^ 10 = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
2 ^ 10 = 1024.000000
NeoBASIC
10 ' Élever à une puissance (groupe 4, fonction 7)
20 print "2 ^ 10 = ";pow(2, 10)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
2 ^ 10 = 1024.000000
Assembleur 65C02 (64tass)
; Élever à une puissance (groupe 4, fonction 7).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  ldx #7                  ; fonction 7 : Power
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $02, $0A, $00, $00, $00, $00, $00, $00
        ; registre 1 : 2 (entier), registre 2 : 10 (entier) (types, puis octets entrelacés)
m:      .text "2 ^ 10 = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
2 ^ 10 = 1024.000000

4,8 Distance (counter-rectangle) Officiel

Registre 1 := racine carrée de (registre 1² + registre 2²) : la distance du point (x, y) à l'origine.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type) ; le registre 2 suit d'un octet
P2uint8pas entre les octets d'un registre
registre 1nombrepremier opérande
registre 2nombresecond opérande
Sorties
OctetsTypeRôle
registre 1nombredistance (flottant)

Pas de mot-clé NeoBASIC : l'exemple BASIC écrit les registres avec poke.

Texte de la documentation du firmware (anglais)

Register1 := Square root of (Register1 * Register1) + (Register2 * Register2)

C (llvm-mos)
/* Distance à l'origine d'un point (groupe 4, fonction 8). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 3);                               /* registre 1 */
    entier(2, 4);                               /* registre 2 */
    calcul(8);                                      /* Distance (counter-rectangle) */
    printf("distance(3, 4) = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
distance(3, 4) = 5.000000
Mad Pascal
// Distance à l'origine d'un point (groupe 4, fonction 8).
program calcul8;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;
    b: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := 3;
  b := 4;
  SetMathStack(a, 0);                          // position 0 d'abord (voir 4,0)
  SetMathStack(b, 1);
  calcul(8);                                 // Distance (counter-rectangle)
  writeln('distance(3, 4) = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
distance(3, 4) = 5.000000
NeoBASIC
10 ' Distance à l'origine d'un point (groupe 4, fonction 8)
20 r = alloc(10) : for i = 0 to 9 : poke r + i, 0 : next i
30 poke r + 2, 3 : poke r + 3, 4 : ' registre 1 : 3, registre 2 : 4 (entiers, pas de 2)
40 while peek($ff00) : wend
50 poke $ff04, r & 255 : poke $ff05, r >> 8 : poke $ff06, 2 : poke $ff01, 8 : poke $ff00, 4
60 while peek($ff00) : wend : t = alloc(34)
70 poke $ff04, r & 255 : poke $ff05, r >> 8 : poke $ff06, 2 : poke $ff08, t & 255 : poke $ff09, t >> 8 : poke $ff01, 34 : poke $ff00, 4
80 while peek($ff00) : wend : b = t : s$ = "" : for i = 1 to peek(b) : s$ = s$ + chr$(peek(b + i)) : next i
90 print "distance(3, 4) = ";s$
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
distance(3, 4) = 5.000000
Assembleur 65C02 (64tass)
; Distance à l'origine d'un point (groupe 4, fonction 8).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  ldx #8                  ; fonction 8 : Distance (counter-rectangle)
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $03, $04, $00, $00, $00, $00, $00, $00
        ; registre 1 : 3 (entier), registre 2 : 4 (entier) (types, puis octets entrelacés)
m:      .text "distance(3, 4) = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
distance(3, 4) = 5.000000

4,9 Angle calculation (arctangent2) Officiel

Registre 1 := arc tangente de registre 1 / registre 2, dans le bon quadrant : l'angle du point (x = registre 2, y = registre 1).

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type) ; le registre 2 suit d'un octet
P2uint8pas entre les octets d'un registre
registre 1nombrepremier opérande
registre 2nombresecond opérande
Sorties
OctetsTypeRôle
registre 1nombreangle, en degrés ou en radians selon 4,35

Le firmware calcule atan2(registre 1, registre 2) : le registre 1 est l'ordonnée. En NeoBASIC, atan2(y, x) fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := arctangent2(Register 1,Register 2) - angle in degrees/radians

C (llvm-mos)
/* Angle d'un point (groupe 4, fonction 9). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 1);                               /* registre 1 */
    entier(2, 1);                               /* registre 2 */
    calcul(9);                                      /* Angle calculation (arctangent2) */
    printf("atan2(1, 1) = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
atan2(1, 1) = 45.000000
Mad Pascal
// Angle d'un point (groupe 4, fonction 9).
program calcul9;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;
    b: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  NeoWaitMessage;
  SetDegreeMode;                                // Mad Pascal démarre en radians
  a := 1;
  b := 1;
  SetMathStack(a, 0);                          // position 0 d'abord (voir 4,0)
  SetMathStack(b, 1);
  calcul(9);                                 // Angle calculation (arctangent2)
  writeln('atan2(1, 1) = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
atan2(1, 1) = 45.000000
NeoBASIC
10 ' Angle d'un point (groupe 4, fonction 9)
20 print "atan2(1, 1) = ";atan2(1, 1)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
atan2(1, 1) = 45.000000
Assembleur 65C02 (64tass)
; Angle d'un point (groupe 4, fonction 9).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  ldx #9                  ; fonction 9 : Angle calculation (arctangent2)
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $01, $01, $00, $00, $00, $00, $00, $00
        ; registre 1 : 1 (entier), registre 2 : 1 (entier) (types, puis octets entrelacés)
m:      .text "atan2(1, 1) = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
atan2(1, 1) = 45.000000

4,16 Negate Officiel

Registre 1 := −registre 1.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
registre 1nombreopérande
Sorties
OctetsTypeRôle
registre 1nombreopposé, du même type

En NeoBASIC, le moins unaire fait cet appel pour un flottant ; pour un entier, il n'est pas fait (observé au banc).

Texte de la documentation du firmware (anglais)

Register1 := -Register 1

C (llvm-mos)
/* Changer de signe (groupe 4, fonction 16). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    flottant(1, 2.5f);                          /* registre 1 */
    calcul(16);                                     /* Negate */
    printf("-(2.5) = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
-(2.5) = -2.500000
Mad Pascal
// Changer de signe (groupe 4, fonction 16).
program calcul16;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: float;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := 2.5;
  SetMathStack(a, 0);
  calcul(16);                                // Negate
  writeln('-(2.5) = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
-(2.5) = -2.500000
NeoBASIC
10 ' Changer de signe (groupe 4, fonction 16)
20 n = 2.5 : print "-(2.5) = ";-n
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
-(2.5) = -2.500000
Assembleur 65C02 (64tass)
; Changer de signe (groupe 4, fonction 16).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  ldx #16                 ; fonction 16 : Negate
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $40, $00, $00, $00, $00, $00, $20, $00, $40, $00
        ; registre 1 : 2.5 (flottant) (types, puis octets entrelacés)
m:      .text "-(2.5) = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
-(2.5) = -2.500000

4,17 Floor Officiel

Registre 1 := plus grand entier inférieur ou égal au registre 1.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
registre 1nombreopérande
Sorties
OctetsTypeRôle
registre 1nombreentier

Le résultat est un entier. Le firmware ne convertit que si l'un des deux registres est marqué flottant (il teste les deux types, comme une opération à deux registres). En NeoBASIC, int( fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := floor(Register 1)

C (llvm-mos)
/* Partie entière par défaut (groupe 4, fonction 17). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    flottant(1, -3.7f);                         /* registre 1 */
    calcul(17);                                     /* Floor */
    printf("floor(-3.7) = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
floor(-3.7) = -4
Mad Pascal
// Partie entière par défaut (groupe 4, fonction 17).
program calcul17;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: float;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := -3.7;
  SetMathStack(a, 0);
  calcul(17);                                // Floor
  writeln('floor(-3.7) = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
floor(-3.7) = -4
NeoBASIC
10 ' Partie entiere par defaut (groupe 4, fonction 17)
20 print "floor(-3.7) = ";int(-3.7)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
floor(-3.7) = -4
Assembleur 65C02 (64tass)
; Partie entière par défaut (groupe 4, fonction 17).
        .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:  ldx #17                 ; fonction 17 : Floor
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $40, $00, $CD, $00, $CC, $00, $6C, $00, $C0, $00
        ; registre 1 : -3.7 (flottant) (types, puis octets entrelacés)
m:      .text "floor(-3.7) = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
floor(-3.7) = -4

4,18 Square Root Officiel

Registre 1 := racine carrée du registre 1.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
registre 1nombreopérande
Sorties
OctetsTypeRôle
registre 1nombreracine (flottant)
erreuruint81 si le registre 1 est négatif

Erreur 1 pour un nombre négatif. En NeoBASIC, sqr( fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := square root(Register 1)

C (llvm-mos)
/* Racine carrée (groupe 4, fonction 18). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 2);                               /* registre 1 */
    calcul(18);                                     /* Square Root */
    printf("sqrt(2) = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
sqrt(2) = 1.414214
Mad Pascal
// Racine carrée (groupe 4, fonction 18).
program calcul18;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := 2;
  SetMathStack(a, 0);
  calcul(18);                                // Square Root
  writeln('sqrt(2) = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
sqrt(2) = 1.414214
NeoBASIC
10 ' Racine carree (groupe 4, fonction 18)
20 print "sqrt(2) = ";sqr(2)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
sqrt(2) = 1.414214
Assembleur 65C02 (64tass)
; Racine carrée (groupe 4, fonction 18).
        .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:  ldx #18                 ; fonction 18 : Square Root
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $02, $00, $00, $00, $00, $00, $00, $00
        ; registre 1 : 2 (entier) (types, puis octets entrelacés)
m:      .text "sqrt(2) = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
sqrt(2) = 1.414214

4,19 Sine Officiel

Registre 1 := sinus du registre 1.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
registre 1nombreopérande
Sorties
OctetsTypeRôle
registre 1nombresinus (flottant)

Angle en degrés par défaut, en radians après 4,35 avec P0 = 0. En NeoBASIC, sin( fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := sine(Register 1) angles in degrees/radians

C (llvm-mos)
/* Sinus (groupe 4, fonction 19). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 30);                              /* registre 1 */
    calcul(19);                                     /* Sine */
    printf("sin(30) = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
sin(30) = 0.500000
Mad Pascal
// Sinus (groupe 4, fonction 19).
program calcul19;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  NeoWaitMessage;
  SetDegreeMode;                                // Mad Pascal démarre en radians
  a := 30;
  SetMathStack(a, 0);
  calcul(19);                                // Sine
  writeln('sin(30) = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
sin(30) = 0.500000
NeoBASIC
10 ' Sinus (groupe 4, fonction 19)
20 print "sin(30) = ";sin(30)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
sin(30) = 0.500000
Assembleur 65C02 (64tass)
; Sinus (groupe 4, fonction 19).
        .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:  ldx #19                 ; fonction 19 : Sine
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $1E, $00, $00, $00, $00, $00, $00, $00
        ; registre 1 : 30 (entier) (types, puis octets entrelacés)
m:      .text "sin(30) = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
sin(30) = 0.500000

4,20 Cosine Officiel

Registre 1 := cosinus du registre 1.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
registre 1nombreopérande
Sorties
OctetsTypeRôle
registre 1nombrecosinus (flottant)

Angle en degrés par défaut (voir 4,35). En NeoBASIC, cos( fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := cosine(Register 1) angles in degrees/radians

C (llvm-mos)
/* Cosinus (groupe 4, fonction 20). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 60);                              /* registre 1 */
    calcul(20);                                     /* Cosine */
    printf("cos(60) = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
cos(60) = 0.500000
Mad Pascal
// Cosinus (groupe 4, fonction 20).
program calcul20;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  NeoWaitMessage;
  SetDegreeMode;                                // Mad Pascal démarre en radians
  a := 60;
  SetMathStack(a, 0);
  calcul(20);                                // Cosine
  writeln('cos(60) = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
cos(60) = 0.500000
NeoBASIC
10 ' Cosinus (groupe 4, fonction 20)
20 print "cos(60) = ";cos(60)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
cos(60) = 0.500000
Assembleur 65C02 (64tass)
; Cosinus (groupe 4, fonction 20).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  ldx #20                 ; fonction 20 : Cosine
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $3C, $00, $00, $00, $00, $00, $00, $00
        ; registre 1 : 60 (entier) (types, puis octets entrelacés)
m:      .text "cos(60) = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
cos(60) = 0.500000

4,21 Tangent Officiel

Registre 1 := tangente du registre 1.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
registre 1nombreopérande
Sorties
OctetsTypeRôle
registre 1nombretangente (flottant)

Angle en degrés par défaut (voir 4,35). En NeoBASIC, tan( fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := tangent(Register 1) angles in degrees/radians

C (llvm-mos)
/* Tangente (groupe 4, fonction 21). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 45);                              /* registre 1 */
    calcul(21);                                     /* Tangent */
    printf("tan(45) = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
tan(45) = 1.000000
Mad Pascal
// Tangente (groupe 4, fonction 21).
program calcul21;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  NeoWaitMessage;
  SetDegreeMode;                                // Mad Pascal démarre en radians
  a := 45;
  SetMathStack(a, 0);
  calcul(21);                                // Tangent
  writeln('tan(45) = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
tan(45) = 1.000000
NeoBASIC
10 ' Tangente (groupe 4, fonction 21)
20 print "tan(45) = ";tan(45)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
tan(45) = 1.000000
Assembleur 65C02 (64tass)
; Tangente (groupe 4, fonction 21).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  ldx #21                 ; fonction 21 : Tangent
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $2D, $00, $00, $00, $00, $00, $00, $00
        ; registre 1 : 45 (entier) (types, puis octets entrelacés)
m:      .text "tan(45) = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
tan(45) = 1.000000

4,22 Arctangent Officiel

Registre 1 := arc tangente du registre 1.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
registre 1nombreopérande
Sorties
OctetsTypeRôle
registre 1nombreangle (flottant), en degrés ou en radians selon 4,35

En NeoBASIC, atan( fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := arctangent(Register 1) angles in degrees/radians

C (llvm-mos)
/* Arc tangente (groupe 4, fonction 22). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 1);                               /* registre 1 */
    calcul(22);                                     /* Arctangent */
    printf("atan(1) = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
atan(1) = 45.000000
Mad Pascal
// Arc tangente (groupe 4, fonction 22).
program calcul22;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  NeoWaitMessage;
  SetDegreeMode;                                // Mad Pascal démarre en radians
  a := 1;
  SetMathStack(a, 0);
  calcul(22);                                // Arctangent
  writeln('atan(1) = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
atan(1) = 45.000000
NeoBASIC
10 ' Arc tangente (groupe 4, fonction 22)
20 print "atan(1) = ";atan(1)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
atan(1) = 45.000000
Assembleur 65C02 (64tass)
; Arc tangente (groupe 4, fonction 22).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  ldx #22                 ; fonction 22 : Arctangent
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $01, $00, $00, $00, $00, $00, $00, $00
        ; registre 1 : 1 (entier) (types, puis octets entrelacés)
m:      .text "atan(1) = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
atan(1) = 45.000000

4,23 Exponent Officiel

Registre 1 := e puissance registre 1.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
registre 1nombreopérande
Sorties
OctetsTypeRôle
registre 1nombreexponentielle (flottant)

En NeoBASIC, exp( fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := e to the power of Register 1

C (llvm-mos)
/* Exponentielle (groupe 4, fonction 23). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 1);                               /* registre 1 */
    calcul(23);                                     /* Exponent */
    printf("exp(1) = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
exp(1) = 2.718282
Mad Pascal
// Exponentielle (groupe 4, fonction 23).
program calcul23;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := 1;
  SetMathStack(a, 0);
  calcul(23);                                // Exponent
  writeln('exp(1) = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
exp(1) = 2.718282
NeoBASIC
10 ' Exponentielle (groupe 4, fonction 23)
20 print "exp(1) = ";exp(1)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
exp(1) = 2.718282
Assembleur 65C02 (64tass)
; Exponentielle (groupe 4, fonction 23).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  ldx #23                 ; fonction 23 : Exponent
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $01, $00, $00, $00, $00, $00, $00, $00
        ; registre 1 : 1 (entier) (types, puis octets entrelacés)
m:      .text "exp(1) = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
exp(1) = 2.718282

4,24 Logarithm Officiel

Registre 1 := logarithme népérien du registre 1.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
registre 1nombreopérande
Sorties
OctetsTypeRôle
registre 1nombrelogarithme (flottant)
erreuruint81 si le registre 1 est négatif

Erreur 1 pour un nombre négatif. En NeoBASIC, log( fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := log(Register 1) natural logarithm

C (llvm-mos)
/* Logarithme népérien (groupe 4, fonction 24). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 10);                              /* registre 1 */
    calcul(24);                                     /* Logarithm */
    printf("log(10) = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
log(10) = 2.302585
Mad Pascal
// Logarithme népérien (groupe 4, fonction 24).
program calcul24;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := 10;
  SetMathStack(a, 0);
  calcul(24);                                // Logarithm
  writeln('log(10) = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
log(10) = 2.302585
NeoBASIC
10 ' Logarithme neperien (groupe 4, fonction 24)
20 print "log(10) = ";log(10)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
log(10) = 2.302585
Assembleur 65C02 (64tass)
; Logarithme népérien (groupe 4, fonction 24).
        .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:  ldx #24                 ; fonction 24 : Logarithm
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $0A, $00, $00, $00, $00, $00, $00, $00
        ; registre 1 : 10 (entier) (types, puis octets entrelacés)
m:      .text "log(10) = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
log(10) = 2.302585

4,25 Absolute Value Officiel

Registre 1 := valeur absolue du registre 1.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
registre 1nombreopérande
Sorties
OctetsTypeRôle
registre 1nombrevaleur absolue, du même type

En NeoBASIC, abs( fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := absolute value(Register 1)

C (llvm-mos)
/* Valeur absolue (groupe 4, fonction 25). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    flottant(1, -7.25f);                        /* registre 1 */
    calcul(25);                                     /* Absolute Value */
    printf("abs(-7.25) = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abs(-7.25) = 7.250000
Mad Pascal
// Valeur absolue (groupe 4, fonction 25).
program calcul25;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: float;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := -7.25;
  SetMathStack(a, 0);
  calcul(25);                                // Absolute Value
  writeln('abs(-7.25) = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abs(-7.25) = 7.250000
NeoBASIC
10 ' Valeur absolue (groupe 4, fonction 25)
20 print "abs(-7.25) = ";abs(-7.25)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abs(-7.25) = 7.250000
Assembleur 65C02 (64tass)
; Valeur absolue (groupe 4, fonction 25).
        .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:  ldx #25                 ; fonction 25 : Absolute Value
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $40, $00, $00, $00, $00, $00, $E8, $00, $C0, $00
        ; registre 1 : -7.25 (flottant) (types, puis octets entrelacés)
m:      .text "abs(-7.25) = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
abs(-7.25) = 7.250000

4,26 Sign Officiel

Registre 1 := signe du registre 1 : −1, 0 ou 1.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
registre 1nombreopérande
Sorties
OctetsTypeRôle
registre 1nombre−1, 0 ou 1 (entier)

En NeoBASIC, sgn( fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := sign(Register 1), returns -1 0 or 1

C (llvm-mos)
/* Signe (groupe 4, fonction 26). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    flottant(1, -3.5f);                         /* registre 1 */
    calcul(26);                                     /* Sign */
    printf("sgn(-3.5) = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
sgn(-3.5) = -1
Mad Pascal
// Signe (groupe 4, fonction 26).
program calcul26;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: float;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := -3.5;
  SetMathStack(a, 0);
  calcul(26);                                // Sign
  writeln('sgn(-3.5) = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
sgn(-3.5) = -1
NeoBASIC
10 ' Signe (groupe 4, fonction 26)
20 print "sgn(-3.5) = ";sgn(-3.5)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
sgn(-3.5) = -1
Assembleur 65C02 (64tass)
; Signe (groupe 4, fonction 26).
        .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:  ldx #26                 ; fonction 26 : Sign
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $40, $00, $00, $00, $00, $00, $60, $00, $C0, $00
        ; registre 1 : -3.5 (flottant) (types, puis octets entrelacés)
m:      .text "sgn(-3.5) = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
sgn(-3.5) = -1

4,27 Random Decimal Officiel

Registre 1 := nombre au hasard entre 0 (compris) et 1 (exclu).

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
Sorties
OctetsTypeRôle
registre 1nombrenombre au hasard (flottant)

Le firmware tire un entier de 0 à 31999 et le divise par 32000 : 32000 valeurs possibles. En NeoBASIC, rnd( fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := random float from 0-1

C (llvm-mos)
/* Tirer un nombre au hasard entre 0 et 1 (groupe 4, fonction 27). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    calcul(27);                                 /* Random Decimal */
    printf("Hasard : %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Hasard : 0.043219
Mad Pascal
// Tirer un nombre au hasard entre 0 et 1 (groupe 4, fonction 27).
program hasard;
uses crt, neo6502, neo6502math;
var s: string[32];

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  calcul(MATHFRnd);                             // Random Decimal
  writeln('Hasard : ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Hasard : 0.043219
NeoBASIC
10 ' Tirer un nombre au hasard entre 0 et 1 (groupe 4, fonction 27)
20 print "Hasard : ";rnd(1)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Hasard : 0.043219
Assembleur 65C02 (64tass)
; Tirer un nombre au hasard entre 0 et 1 (groupe 4, fonction 27).
        .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:  ldx #27                    ; fonction 27 : Random Decimal
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .fill 10
m:      .text "Hasard : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Hasard : 0.043219

4,28 Random Integer Officiel

Registre 1 := entier au hasard de 0 à (registre 1 − 1).

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
registre 1nombreopérande
Sorties
OctetsTypeRôle
registre 1nombreentier au hasard

Si le registre 1 vaut 0 ou moins, il reste inchangé. En NeoBASIC, rand( fait cet appel.

Texte de la documentation du firmware (anglais)

Register1 := random integer from 0 to (Register 1-1)

C (llvm-mos)
/* Lancer un dé à 6 faces (groupe 4, fonction 28). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, 6);                               /* registre 1 */
    calcul(28);                                     /* Random Integer */
    printf("Tirage de 0 a 5 : %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Tirage de 0 a 5 : 1
Mad Pascal
// Lancer un dé à 6 faces (groupe 4, fonction 28).
program calcul28;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := 6;
  SetMathStack(a, 0);
  calcul(28);                                // Random Integer
  writeln('Tirage de 0 a 5 : ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Tirage de 0 a 5 : 1
NeoBASIC
10 ' Lancer un de à 6 faces (groupe 4, fonction 28)
20 print "Tirage de 0 a 5 : ";rand(6)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Tirage de 0 a 5 : 1
Assembleur 65C02 (64tass)
; Lancer un dé à 6 faces (groupe 4, fonction 28).
        .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:  ldx #28                 ; fonction 28 : Random Integer
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $06, $00, $00, $00, $00, $00, $00, $00
        ; registre 1 : 6 (entier) (types, puis octets entrelacés)
m:      .text "Tirage de 0 a 5 : ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
Tirage de 0 a 5 : 1

4,32 Number to Decimal Officiel

Ajoute au registre 1 une partie décimale donnée en chiffres BCD : c'est l'outil du tokeniseur de NeoBASIC pour les constantes décimales.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
registre 1nombrepartie entière
P4-P5addradresse des chiffres après la virgule, deux par octet (BCD), terminés par un quartet $F
Sorties
OctetsTypeRôle
registre 1nombreregistre 1 + 0,chiffres (flottant)

La documentation du firmware dit de ne pas l'utiliser : c'est un outil interne de NeoBASIC, qui l'appelle pour chaque constante décimale d'un programme (1.5, 3.14…). L'unité neo6502math de Mad Pascal l'enveloppe dans AddFractionalBCD. Exemple : 3 et les chiffres 1 4 1 5 9 ($14 $15 $9F) donnent 3,14159.

Texte de la documentation du firmware (anglais)

Helper function for tokeniser, do not use.

C (llvm-mos)
/* Ajouter une partie décimale en BCD (groupe 4, fonction 32). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

static const uint8_t chiffres[] = { 0x14, 0x15, 0x9F };   /* 1 4 1 5 9, fin : $F */

int main(void) {
    entier(1, 3);                               /* registre 1 : partie entière */
    ControlPort.params[4] = (uint16_t)chiffres & 0xFF;  /* P4-P5 : chiffres */
    ControlPort.params[5] = (uint16_t)chiffres >> 8;
    calcul(32);                                 /* Number to Decimal */
    printf("3 + 0,14159 = %s\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
3 + 0,14159 = 3.141590
Mad Pascal
// Ajouter une partie décimale en BCD (groupe 4, fonction 32).
program decimales;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;
    chiffres: array[0..2] of byte = ($14, $15, $9F);   // 1 4 1 5 9, fin : $F

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := 3;
  SetMathStack(a, 0);                          // registre 1 : partie entière
  wordParams[2] := word(@chiffres);             // P4-P5 : chiffres
  calcul(MATHProcessDecimal);                   // Number to Decimal
  writeln('3 + 0,14159 = ', texte);
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
3 + 0,14159 = 3.141590
NeoBASIC
10 ' Ajouter une partie decimale en BCD (groupe 4, fonction 32)
20 ' NeoBASIC fait cet appel pour chaque constante decimale, ici 3.14159
30 print "3 + 0,14159 = ";3.14159
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
3 + 0,14159 = 3.141590
Assembleur 65C02 (64tass)
; Ajouter une partie décimale en BCD (groupe 4, fonction 32).
        .cpu "65c02"
        * = $0800
ControlPort    = $FF00             ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage    = $FFF4             ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1             ; affiche le caractère de A

start:  lda #<chiffres
        sta ControlPort+8          ; P4-P5 : chiffres
        lda #>chiffres
        sta ControlPort+9
        ldx #32                    ; fonction 32 : Number to Decimal
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jmp WriteCharacter

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $03, $00, $00, $00, $00, $00, $00, $00
        ; registre 1 : 3 (entier) (types, puis octets entrelacés)
chiffres: .byte $14, $15, $9F     ; 1 4 1 5 9, fin : $F
m:      .text "3 + 0,14159 = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
3 + 0,14159 = 3.141590

4,33 String to Number Officiel

Convertit un texte en nombre dans le registre 1 : entier s'il n'a pas de partie décimale, flottant sinon.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
P4-P5addradresse du texte (précédé de sa longueur)
Sorties
OctetsTypeRôle
registre 1nombrenombre
erreuruint81 si le texte n'est pas un nombre

L'exemple convertit « 2.5 » puis affiche le type obtenu ($40 : flottant). En NeoBASIC, val( fait cet appel, de même que input pour un nombre. L'unité neo6502math de Mad Pascal l'utilise dans NeoParseInt et NeoParseFloat.

Texte de la documentation du firmware (anglais)

Convert the length prefixed string at Parameters:4,5 to a constant in Register1.

C (llvm-mos)
/* Convertir un texte en nombre (groupe 4, fonction 33). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

static const uint8_t nombre[] = "\x03" "2.5";

int main(void) {
    ControlPort.params[4] = (uint16_t)nombre & 0xFF;    /* P4-P5 : texte */
    ControlPort.params[5] = (uint16_t)nombre >> 8;
    calcul(33);                                 /* String to Number */
    uint8_t type = reg[0];                      /* $40 : flottant */
    printf("\"2.5\" -> %s (type %u)\n", en_texte(), type);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
"2.5" -> 2.500000 (type 64)
Mad Pascal
// Convertir un texte en nombre (groupe 4, fonction 33).
program valeur;
uses crt, neo6502, neo6502math;
var s: string[32];
    nombre: string[8];
    t: byte;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  nombre := '2.5';
  wordParams[2] := word(@nombre);               // P4-P5 : texte
  calcul(MATHConvertStringToNumber);            // String to Number
  t := peek($F5);                               // type du registre 1 : $40, flottant
  writeln('"2.5" -> ', texte, ' (type ', t, ')');
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
"2.5" -> 2.500000 (type 64)
NeoBASIC
10 ' Convertir un texte en nombre (groupe 4, fonction 33)
20 print chr$(34);"2.5";chr$(34);" -> ";val("2.5")
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
"2.5" -> 2.500000
Assembleur 65C02 (64tass)
; Convertir un texte en nombre (groupe 4, fonction 33).
        .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 #<nombre
        sta ControlPort+8          ; P4-P5 : texte
        lda #>nombre
        sta ControlPort+9
        ldx #33                    ; fonction 33 : String to Number
        jsr calcul
        lda reg                    ; type du registre 1 : $40, flottant
        sta type
        lda #<m1
        ldx #>m1
        jsr ecrire
        jsr affiche
        lda #<m2
        ldx #>m2
        jsr ecrire
        lda type
        jsr decimal
        lda #<m3
        ldx #>m3
        jmp ecrire

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .fill 10
nombre: .byte 3
        .text "2.5"
type:   .byte 0
m1:     .text '"2.5" -> ', 0
m2:     .text " (type ", 0
m3:     .text ")", 13, 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
"2.5" -> 2.500000 (type 64)

4,34 Number to String Officiel

Convertit le registre 1 en texte (précédé de sa longueur) : entier en décimal, flottant avec 6 décimales.

Entrées
OctetsTypeRôle
P0-P1addradresse du registre 1 (octet de type)
P2uint8pas entre les octets du registre
registre 1nombreopérande
P4-P5addradresse du tampon du texte
Sorties
OctetsTypeRôle
tamponstringtexte (précédé de sa longueur)

Format du C : %d pour un entier, %f pour un flottant (0.250000). Sur Trinity, l'écriture est bornée à la fin de la mémoire du 65C02 (T-59) ; le firmware officiel écrit autant de caractères que le nombre en demande. NeoBASIC fait cet appel pour afficher un nombre (print) et dans str$(.

Texte de la documentation du firmware (anglais)

Convert the constant in Register1 to a length prefixed string which is stored at Parameters:4,5

C (llvm-mos)
/* Convertir des nombres en texte (groupe 4, fonction 34). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

int main(void) {
    entier(1, -123);
    printf("-123 -> \"%s\"\n", en_texte());  /* en_texte : Number to String */
    flottant(1, 0.25f);
    printf("0.25 -> \"%s\"\n", en_texte());
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
-123 -> "-123"
0.25 -> "0.250000"
Mad Pascal
// Convertir des nombres en texte (groupe 4, fonction 34).
program texte34;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;
    b: float;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  a := -123;
  SetMathStack(a, 0);
  writeln('-123 -> "', texte, '"');             // texte : Number to String
  b := 0.25;
  SetMathStack(b, 0);
  writeln('0.25 -> "', texte, '"');
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
-123 -> "-123"
0.25 -> "0.250000"
NeoBASIC
10 ' Convertir des nombres en texte (groupe 4, fonction 34)
20 print "-123 -> ";chr$(34);str$(-123);chr$(34)
30 print "0.25 -> ";chr$(34);str$(0.25);chr$(34)
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
-123 -> "-123"
0.25 -> "0.250000"
Assembleur 65C02 (64tass)
; Convertir des nombres en texte (groupe 4, fonction 34).
        .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 #<m1
        ldx #>m1
        jsr ecrire
        jsr affiche                ; affiche : fonction 34, Number to String
        lda #<m2
        ldx #>m2
        jsr ecrire
        ldx #9
_copie: lda quart,x                ; registre 1 := 0.25
        sta reg,x
        dex
        bpl _copie
        lda #<m3
        ldx #>m3
        jsr ecrire
        jsr affiche
        lda #<m2
        ldx #>m2
        jmp ecrire

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $85, $00, $FF, $00, $FF, $00, $FF, $00
        ; registre 1 : -123 (entier) (types, puis octets entrelacés)
quart:  .byte $40, $00, $00, $00, $00, $00, $80, $00, $3E, $00
        ; registre 1 : 0.25 (flottant) (types, puis octets entrelacés)
m1:     .text '-123 -> "', 0
m2:     .text '"', 13, 0
m3:     .text '0.25 -> "', 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
-123 -> "-123"
0.25 -> "0.250000"

4,35 Set Degree/Radian Mode Officiel

Choisit l'unité des angles des fonctions 9, 19 à 22 : degrés (défaut) ou radians.

Entrées
OctetsTypeRôle
P0uint8non nul : degrés ; 0 : radians

Sorties : aucune.

Le réglage vaut pour tous les programmes jusqu'au prochain appel. Le code de démarrage de Mad Pascal 1.7.8 passe en radians ; ses routines SetDegreeMode et SetRadianMode font cet appel. En NeoBASIC, clear (et donc run) remet les degrés. L'exemple passe en radians, calcule atan(1) = π/4, puis revient aux degrés.

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

Texte de la documentation du firmware (anglais)

Sets the use of degrees (the default) when non zero, radians when zero.

C (llvm-mos)
/* Calculer en radians, puis revenir aux degrés (groupe 4, fonction 35). */
#include <stdio.h>
#include <neo6502.h>

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

static uint8_t reg[10];                         /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];

static void entier(uint8_t r, int32_t v) {      /* registre r (1 ou 2) := entier v */
    reg[r - 1] = 0x00;
    for (uint8_t i = 0; i < 4; i++)
        reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) {      /* registre r := flottant v */
    union { float f; int32_t i; } u;
    u.f = v;
    entier(r, u.i);
    reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) {          /* appel du groupe 4 sur les registres */
    libre();
    ControlPort.params[0] = (uint16_t)reg & 0xFF;
    ControlPort.params[1] = (uint16_t)reg >> 8;
    ControlPort.params[2] = 2;                  /* pas */
    api(4, fonction);
}
static const char *en_texte(void) {             /* registre 1 en texte, par 4,34 */
    ControlPort.params[4] = (uint16_t)texte & 0xFF;
    ControlPort.params[5] = (uint16_t)texte >> 8;
    calcul(34);
    texte[(uint8_t)texte[0] + 1] = 0;
    return texte + 1;
}

static void mode(uint8_t degres) {
    libre();
    ControlPort.params[0] = degres;             /* P0 : 0 radians, sinon degrés */
    api(4, 35);                                 /* Set Degree/Radian Mode */
}

int main(void) {
    mode(0);
    entier(1, 1);
    calcul(22);                                 /* 4,22 : arc tangente */
    printf("atan(1) en radians = %s\n", en_texte());
    mode(1);
    return 0;
}
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
atan(1) en radians = 0.785398
Mad Pascal
// Calculer en radians, puis revenir aux degrés (groupe 4, fonction 35).
program radians;
uses crt, neo6502, neo6502math;
var s: string[32];
    a: integer;

procedure calcul(f: byte);                      // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
  DoMathOnStack(f);
  NeoWaitMessage;                               // attendre le résultat
end;

function texte: string;                         // registre 1 en texte, par 4,34
begin
  wordParams[2] := word(@s);                    // P4-P5 : tampon
  calcul(MATHConvertNumberToString);
  result := s;
end;

begin
  NeoWaitMessage;
  SetRadianMode;                                // Set Degree/Radian Mode, P0 = 0
  a := 1;
  SetMathStack(a, 0);
  calcul(MATHATan);                             // 4,22 : arc tangente
  writeln('atan(1) en radians = ', texte);
  NeoWaitMessage;
  SetDegreeMode;                                // P0 = 1
  NeoWaitMessage;
end.
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
atan(1) en radians = 0.785398
NeoBASIC
10 ' Calculer en radians, puis revenir aux degres (groupe 4, fonction 35)
20 while peek($ff00) : wend
30 poke $ff04, 0 : poke $ff01, 35 : poke $ff00, 4 : ' radians
40 while peek($ff00) : wend
50 print "atan(1) en radians = ";atan(1)
60 while peek($ff00) : wend
70 poke $ff04, 1 : poke $ff01, 35 : poke $ff00, 4 : ' degres
80 while peek($ff00) : wend
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
atan(1) en radians = 0.785398
Assembleur 65C02 (64tass)
; Calculer en radians, puis revenir aux degrés (groupe 4, fonction 35).
        .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 #0
        jsr mode                   ; radians
        ldx #22                    ; 4,22 : arc tangente
        jsr calcul
        lda #<m
        ldx #>m
        jsr ecrire
        jsr affiche
        lda #13
        jsr WriteCharacter
        lda #1                     ; retour aux degrés
mode:   pha
        jsr WaitMessage
        pla
        sta ControlPort+4          ; P0 : 0 radians, sinon degrés
        lda #4
        ldx #35                    ; fonction 35 : Set Degree/Radian Mode
        jmp appel

; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
        lda #<reg
        sta ControlPort+4          ; P0-P1 : registre 1
        lda #>reg
        sta ControlPort+5
        lda #2
        sta ControlPort+6          ; P2 : pas
        lda #4
        jmp appel

; Affiche le registre 1, converti en texte par 4,34.
affiche:
        jsr WaitMessage
        lda #<texte
        sta ControlPort+8          ; P4-P5 : tampon
        lda #>texte
        sta ControlPort+9
        ldx #34
        jsr calcul
        lda #<texte
        ldx #>texte
        jmp pecrire
texte:  .fill 34

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

; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
        stx ptr+1
        ldy #0
_e:     lda (ptr),y
        beq _f
        jsr WriteCharacter
        iny
        bne _e
_f:     rts

; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
        phx
        phy
        ldx #0
        ldy #100
        jsr _chiffre
        ldy #10
        jsr _chiffre
        ora #'0'
        jsr WriteCharacter
        ply
        plx
        rts
_chiffre:
        sty diviseur
        ldy #0
_div:   cmp diviseur
        bcc _fini
        sbc diviseur
        iny
        bne _div
_fini:  pha
        tya
        bne _ecrit
        cpx #0
        beq _saute
_ecrit: ora #'0'
        jsr WriteCharacter
        ldx #1
_saute: pla
        rts

; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel:  stx ControlPort+1
        sta ControlPort            ; écrit en dernier : lance l'appel
        jmp WaitMessage

ptr      = $80
diviseur: .byte 0

reg:    .byte $00, $00, $01, $00, $00, $00, $00, $00, $00, $00
        ; registre 1 : 1 (entier) (types, puis octets entrelacés)
m:      .text "atan(1) en radians = ", 0
Sortie observée dans l'émulateur Phosphoneo, firmware Trinity 0.16.69 :
atan(1) en radians = 0.785398

← L'API du Neo6502