Group 4 — Mathematics Official
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
Group 4 is a maths coprocessor: the RP2040 computes in 32-bit integers or single-precision floats (IEEE 754) for the 65C02. Numbers do not go through the mailbox but through two registers kept in 65C02 memory, whose address each call gives.
A register is 5 bytes: a type byte ($00 integer, $40 float), then the 4 bytes of the value, low byte first. P0-P1 gives the address of the type byte of register 1; that of register 2 is at the next byte. P2 gives the step between two bytes of the same register: with a step of 2, both registers are interleaved over 10 bytes (types, then byte 0 of both values, then byte 1…). This is the layout of the examples, and that of the Mad Pascal neo6502math unit; NeoBASIC keeps its expression stack this way.
The result comes back in register 1, with its type. A two-register operation computes in floating point as soon as one of the two is a float, in integers otherwise. To print a result, the examples convert it to text with 4,34, which gives the firmware format (6 decimals for a float).
Angles are in degrees by default; 4,35 switches to radians. Starting a Mad Pascal program switches to radians (Mad Pascal 1.7.8 start-up code): the Pascal examples that use angles switch back to degrees.
4,0 Addition Official
Register 1 := register 1 + register 2.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte); register 2 is one byte further |
P2 | uint8 | step between the bytes of a register |
registre 1 | nombre | first operand |
registre 2 | nombre | second operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | sum (float if either operand is) |
Mad Pascal neo6502math unit (version 0.30.0): SetMathStack(v, 0) also writes position 1 (the position 0 code falls through into the position 1 code). Position 0 must therefore be set before position 1; in the other order, both registers hold the first number (checked: 7 \ 2 then gives 1). In NeoBASIC, + uses this call for floats; two integers are added by the 65C02.
Firmware documentation text
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;
}1.5 + 2.25 = 3.750000Mad 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.1.5 + 2.25 = 3.750000NeoBASIC
10 ' Additionner deux nombres (groupe 4, fonction 0)
20 print "1.5 + 2.25 = ";1.5 + 2.251.5 + 2.25 = 3.75000065C02 assembly (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 = ", 01.5 + 2.25 = 3.7500004,1 Subtraction Official
Register 1 := register 1 − register 2.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte); register 2 is one byte further |
P2 | uint8 | step between the bytes of a register |
registre 1 | nombre | first operand |
registre 2 | nombre | second operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | difference |
An integer and a float: the computation is done in floating point. In NeoBASIC, - uses this call for floats.
Firmware documentation text
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;
}10 - 25.5 = -15.500000Mad 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.10 - 25.5 = -15.500000NeoBASIC
10 ' Soustraire deux nombres (groupe 4, fonction 1)
20 print "10 - 25.5 = ";10 - 25.510 - 25.5 = -15.50000065C02 assembly (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 = ", 010 - 25.5 = -15.5000004,2 Multiplication Official
Register 1 := register 1 × register 2.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte); register 2 is one byte further |
P2 | uint8 | step between the bytes of a register |
registre 1 | nombre | first operand |
registre 2 | nombre | second operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | product (integer if both operands are) |
Two integers give a 32-bit integer (no overflow check). In NeoBASIC, * always uses this call.
Firmware documentation text
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;
}6 * 7 = 42Mad 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.6 * 7 = 42NeoBASIC
10 ' Multiplier deux entiers (groupe 4, fonction 2)
20 print "6 * 7 = ";6 * 76 * 7 = 4265C02 assembly (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 = ", 06 * 7 = 424,3 Decimal Division Official
Register 1 := register 1 / register 2, always in floating point.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte); register 2 is one byte further |
P2 | uint8 | step between the bytes of a register |
registre 1 | nombre | first operand |
registre 2 | nombre | second operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | quotient (float) |
erreur | uint8 | 1 if register 2 is 0 |
Even with two integers, the result is a float. In NeoBASIC, / makes this call.
Firmware documentation text
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;
}7 / 2 = 3.500000Mad 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.7 / 2 = 3.500000NeoBASIC
10 ' Diviser en flottant (groupe 4, fonction 3)
20 print "7 / 2 = ";7 / 27 / 2 = 3.50000065C02 assembly (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 = ", 07 / 2 = 3.5000004,4 Integer Division Official
Register 1 := register 1 / register 2, in integers (truncated quotient).
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte); register 2 is one byte further |
P2 | uint8 | step between the bytes of a register |
registre 1 | nombre | first operand |
registre 2 | nombre | second operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | integer quotient |
erreur | uint8 | 1 if register 2 is 0 |
Floats are converted to integers first. In NeoBASIC, \ makes this call.
Firmware documentation text
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;
}7 \ 2 = 3Mad 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.7 \ 2 = 3NeoBASIC
10 ' Diviser en entier (groupe 4, fonction 4)
20 print "7 \ 2 = ";7 \ 27 \ 2 = 365C02 assembly (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 = ", 07 \ 2 = 34,5 Integer Modulus Official
Register 1 := remainder of the integer division of register 1 by register 2, computed on absolute values.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte); register 2 is one byte further |
P2 | uint8 | step between the bytes of a register |
registre 1 | nombre | first operand |
registre 2 | nombre | second operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | remainder (always zero or positive) |
erreur | uint8 | 1 if register 2 is 0 |
The firmware takes the absolute values of both operands: -17 % 5 gives 2 (not -2 as in C). In NeoBASIC, % makes this call.
Firmware documentation text
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;
}-17 % 5 = 2Mad 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.-17 % 5 = 2NeoBASIC
10 ' Reste d'une division entiere (groupe 4, fonction 5)
20 n = -17 : print "-17 % 5 = ";n % 5-17 % 5 = 265C02 assembly (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-17 % 5 = 24,6 Compare Official
Compares register 1 and register 2; the result comes back in P0.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte); register 2 is one byte further |
P2 | uint8 | step between the bytes of a register |
registre 1 | nombre | first operand |
registre 2 | nombre | second operand |
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | $FF if register 1 < register 2, 0 if equal, 1 if greater |
Between floats, the comparison is approximate: two numbers whose difference is below one ten-millionth of their size are equal. In NeoBASIC, float comparisons (<, =, >…) make this call; integer ones are done on the 65C02.
Firmware documentation text
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;
}compare(2.5, 3.5) = 255Mad 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.compare(2.5, 3.5) = 255NeoBASIC
10 ' Comparer deux flottants (groupe 4, fonction 6)
20 print "2.5 < 3.5 : ";2.5 < 3.52.5 < 3.5 : -165C02 assembly (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) = ", 0compare(2.5, 3.5) = 2554,7 Power Official
Register 1 := register 1 raised to the power of register 2, in floating point.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte); register 2 is one byte further |
P2 | uint8 | step between the bytes of a register |
registre 1 | nombre | first operand |
registre 2 | nombre | second operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | power (float) |
The result is always a float. In NeoBASIC, pow(a, b) makes this call.
Firmware documentation text
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;
}2 ^ 10 = 1024.000000Mad 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.2 ^ 10 = 1024.000000NeoBASIC
10 ' Élever à une puissance (groupe 4, fonction 7)
20 print "2 ^ 10 = ";pow(2, 10)2 ^ 10 = 1024.00000065C02 assembly (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 = ", 02 ^ 10 = 1024.0000004,8 Distance (counter-rectangle) Official
Register 1 := square root of (register 1² + register 2²): the distance from point (x, y) to the origin.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte); register 2 is one byte further |
P2 | uint8 | step between the bytes of a register |
registre 1 | nombre | first operand |
registre 2 | nombre | second operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | distance (float) |
No NeoBASIC keyword: the BASIC example writes the registers with poke.
Firmware documentation text
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;
}distance(3, 4) = 5.000000Mad 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.distance(3, 4) = 5.000000NeoBASIC
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$distance(3, 4) = 5.00000065C02 assembly (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) = ", 0distance(3, 4) = 5.0000004,9 Angle calculation (arctangent2) Official
Register 1 := arc tangent of register 1 / register 2, in the right quadrant: the angle of point (x = register 2, y = register 1).
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte); register 2 is one byte further |
P2 | uint8 | step between the bytes of a register |
registre 1 | nombre | first operand |
registre 2 | nombre | second operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | angle, in degrees or radians depending on 4,35 |
The firmware computes atan2(register 1, register 2): register 1 is the ordinate. In NeoBASIC, atan2(y, x) makes this call.
Firmware documentation text
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;
}atan2(1, 1) = 45.000000Mad 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.atan2(1, 1) = 45.000000NeoBASIC
10 ' Angle d'un point (groupe 4, fonction 9)
20 print "atan2(1, 1) = ";atan2(1, 1)atan2(1, 1) = 45.00000065C02 assembly (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) = ", 0atan2(1, 1) = 45.0000004,16 Negate Official
Register 1 := −register 1.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
registre 1 | nombre | operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | opposite, same type |
In NeoBASIC, unary minus makes this call for a float; for an integer, it is not made (observed on the bench).
Firmware documentation text
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;
}-(2.5) = -2.500000Mad 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.-(2.5) = -2.500000NeoBASIC
10 ' Changer de signe (groupe 4, fonction 16)
20 n = 2.5 : print "-(2.5) = ";-n-(2.5) = -2.50000065C02 assembly (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-(2.5) = -2.5000004,17 Floor Official
Register 1 := largest integer less than or equal to register 1.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
registre 1 | nombre | operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | integer |
The result is an integer. The firmware only converts if one of the two registers is marked float (it tests both types, like a two-register operation). In NeoBASIC, int( makes this call.
Firmware documentation text
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;
}floor(-3.7) = -4Mad 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.floor(-3.7) = -4NeoBASIC
10 ' Partie entiere par defaut (groupe 4, fonction 17)
20 print "floor(-3.7) = ";int(-3.7)floor(-3.7) = -465C02 assembly (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) = ", 0floor(-3.7) = -44,18 Square Root Official
Register 1 := square root of register 1.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
registre 1 | nombre | operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | root (float) |
erreur | uint8 | 1 if register 1 is negative |
Error 1 for a negative number. In NeoBASIC, sqr( makes this call.
Firmware documentation text
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;
}sqrt(2) = 1.414214Mad 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.sqrt(2) = 1.414214NeoBASIC
10 ' Racine carree (groupe 4, fonction 18)
20 print "sqrt(2) = ";sqr(2)sqrt(2) = 1.41421465C02 assembly (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) = ", 0sqrt(2) = 1.4142144,19 Sine Official
Register 1 := sine of register 1.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
registre 1 | nombre | operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | sine (float) |
Angle in degrees by default, in radians after 4,35 with P0 = 0. In NeoBASIC, sin( makes this call.
Firmware documentation text
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;
}sin(30) = 0.500000Mad 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.sin(30) = 0.500000NeoBASIC
10 ' Sinus (groupe 4, fonction 19)
20 print "sin(30) = ";sin(30)sin(30) = 0.50000065C02 assembly (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) = ", 0sin(30) = 0.5000004,20 Cosine Official
Register 1 := cosine of register 1.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
registre 1 | nombre | operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | cosine (float) |
Angle in degrees by default (see 4,35). In NeoBASIC, cos( makes this call.
Firmware documentation text
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;
}cos(60) = 0.500000Mad 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.cos(60) = 0.500000NeoBASIC
10 ' Cosinus (groupe 4, fonction 20)
20 print "cos(60) = ";cos(60)cos(60) = 0.50000065C02 assembly (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) = ", 0cos(60) = 0.5000004,21 Tangent Official
Register 1 := tangent of register 1.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
registre 1 | nombre | operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | tangent (float) |
Angle in degrees by default (see 4,35). In NeoBASIC, tan( makes this call.
Firmware documentation text
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;
}tan(45) = 1.000000Mad 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.tan(45) = 1.000000NeoBASIC
10 ' Tangente (groupe 4, fonction 21)
20 print "tan(45) = ";tan(45)tan(45) = 1.00000065C02 assembly (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) = ", 0tan(45) = 1.0000004,22 Arctangent Official
Register 1 := arc tangent of register 1.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
registre 1 | nombre | operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | angle (float), in degrees or radians depending on 4,35 |
In NeoBASIC, atan( makes this call.
Firmware documentation text
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;
}atan(1) = 45.000000Mad 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.atan(1) = 45.000000NeoBASIC
10 ' Arc tangente (groupe 4, fonction 22)
20 print "atan(1) = ";atan(1)atan(1) = 45.00000065C02 assembly (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) = ", 0atan(1) = 45.0000004,23 Exponent Official
Register 1 := e to the power of register 1.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
registre 1 | nombre | operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | exponential (float) |
In NeoBASIC, exp( makes this call.
Firmware documentation text
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;
}exp(1) = 2.718282Mad 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.exp(1) = 2.718282NeoBASIC
10 ' Exponentielle (groupe 4, fonction 23)
20 print "exp(1) = ";exp(1)exp(1) = 2.71828265C02 assembly (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) = ", 0exp(1) = 2.7182824,24 Logarithm Official
Register 1 := natural logarithm of register 1.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
registre 1 | nombre | operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | logarithm (float) |
erreur | uint8 | 1 if register 1 is negative |
Error 1 for a negative number. In NeoBASIC, log( makes this call.
Firmware documentation text
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;
}log(10) = 2.302585Mad 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.log(10) = 2.302585NeoBASIC
10 ' Logarithme neperien (groupe 4, fonction 24)
20 print "log(10) = ";log(10)log(10) = 2.30258565C02 assembly (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) = ", 0log(10) = 2.3025854,25 Absolute Value Official
Register 1 := absolute value of register 1.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
registre 1 | nombre | operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | absolute value, same type |
In NeoBASIC, abs( makes this call.
Firmware documentation text
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;
}abs(-7.25) = 7.250000Mad 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.abs(-7.25) = 7.250000NeoBASIC
10 ' Valeur absolue (groupe 4, fonction 25)
20 print "abs(-7.25) = ";abs(-7.25)abs(-7.25) = 7.25000065C02 assembly (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) = ", 0abs(-7.25) = 7.2500004,26 Sign Official
Register 1 := sign of register 1: −1, 0 or 1.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
registre 1 | nombre | operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | −1, 0 or 1 (integer) |
In NeoBASIC, sgn( makes this call.
Firmware documentation text
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;
}sgn(-3.5) = -1Mad 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.sgn(-3.5) = -1NeoBASIC
10 ' Signe (groupe 4, fonction 26)
20 print "sgn(-3.5) = ";sgn(-3.5)sgn(-3.5) = -165C02 assembly (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) = ", 0sgn(-3.5) = -14,27 Random Decimal Official
Register 1 := random number between 0 (included) and 1 (excluded).
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | random number (float) |
The firmware draws an integer from 0 to 31999 and divides it by 32000: 32000 possible values. In NeoBASIC, rnd( makes this call.
Firmware documentation text
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;
}Hasard : 0.043219Mad 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.Hasard : 0.043219NeoBASIC
10 ' Tirer un nombre au hasard entre 0 et 1 (groupe 4, fonction 27)
20 print "Hasard : ";rnd(1)Hasard : 0.04321965C02 assembly (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 : ", 0Hasard : 0.0432194,28 Random Integer Official
Register 1 := random integer from 0 to (register 1 − 1).
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
registre 1 | nombre | operand |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | random integer |
If register 1 is 0 or less, it is left unchanged. In NeoBASIC, rand( makes this call.
Firmware documentation text
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;
}Tirage de 0 a 5 : 1Mad 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.Tirage de 0 a 5 : 1NeoBASIC
10 ' Lancer un de à 6 faces (groupe 4, fonction 28)
20 print "Tirage de 0 a 5 : ";rand(6)Tirage de 0 a 5 : 165C02 assembly (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 : ", 0Tirage de 0 a 5 : 14,32 Number to Decimal Official
Adds to register 1 a decimal part given as BCD digits: it is the NeoBASIC tokeniser helper for decimal constants.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
registre 1 | nombre | integer part |
P4-P5 | addr | address of the digits after the point, two per byte (BCD), ended by a $F nibble |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | register 1 + 0.digits (float) |
The firmware documentation says not to use it: it is an internal NeoBASIC helper, called for each decimal constant of a program (1.5, 3.14…). The Mad Pascal neo6502math unit wraps it in AddFractionalBCD. Example: 3 and the digits 1 4 1 5 9 ($14 $15 $9F) give 3.14159.
Firmware documentation text
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;
}3 + 0,14159 = 3.141590Mad 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.3 + 0,14159 = 3.141590NeoBASIC
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.141593 + 0,14159 = 3.14159065C02 assembly (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 = ", 03 + 0,14159 = 3.1415904,33 String to Number Official
Converts a text into a number in register 1: integer if it has no decimal part, float otherwise.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
P4-P5 | addr | address of the text (length-prefixed) |
| Bytes | Type | Meaning |
|---|---|---|
registre 1 | nombre | number |
erreur | uint8 | 1 if the text is not a number |
The example converts "2.5" then prints the resulting type ($40: float). In NeoBASIC, val( makes this call, as does input for a number. The Mad Pascal neo6502math unit uses it in NeoParseInt and NeoParseFloat.
Firmware documentation text
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;
}"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."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")"2.5" -> 2.50000065C02 assembly (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"2.5" -> 2.500000 (type 64)4,34 Number to String Official
Converts register 1 into text (length-prefixed): integer in decimal, float with 6 decimals.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of register 1 (type byte) |
P2 | uint8 | step between the bytes of the register |
registre 1 | nombre | operand |
P4-P5 | addr | address of the text buffer |
| Bytes | Type | Meaning |
|---|---|---|
tampon | string | text (length-prefixed) |
C format: %d for an integer, %f for a float (0.250000). On Trinity, the write is bounded to the end of 65C02 memory (T-59); the official firmware writes as many characters as the number needs. NeoBASIC makes this call to print a number (print) and in str$(.
Firmware documentation text
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;
}-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.-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)-123 -> "-123"
0.25 -> "0.250000"65C02 assembly (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-123 -> "-123"
0.25 -> "0.250000"4,35 Set Degree/Radian Mode Official
Selects the angle unit of functions 9, 19 to 22: degrees (default) or radians.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | non zero: degrees; 0: radians |
Outputs: none.
The setting holds for all programs until the next call. The Mad Pascal 1.7.8 start-up code switches to radians; its SetDegreeMode and SetRadianMode routines make this call. In NeoBASIC, clear (and so run) restores degrees. The example switches to radians, computes atan(1) = π/4, then goes back to degrees.
NeoBASIC keywords that make this call: clear
Firmware documentation text
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;
}atan(1) en radians = 0.785398Mad 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.atan(1) en radians = 0.785398NeoBASIC
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) : wendatan(1) en radians = 0.78539865C02 assembly (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 = ", 0atan(1) en radians = 0.785398