Group 32 — QuickDraw Trinity
32,1 Init Graf · 32,2 Set Clip · 32,3 Get Clip · 32,4 Set Pen Colour · 32,5 Move To · 32,6 Get Pen · 32,7 Frame Rect · 32,8 Paint Rect · 32,9 Erase Rect · 32,10 Invert Rect · 32,11 Line To · 32,12 Set Pattern · 32,13 Fill Rect · 32,14 Copy Bits · 32,15 Set Font · 32,16 Draw String · 32,17 Text Width · 32,18 Get Font Info · 32,19 Toolbox Reset
QuickDraw is the drawing layer of the Trinity toolbox (groups 32 to 38). It draws on the draw page, below the sprites, and always inside a clip rectangle.
Structures live in 6502 RAM and are passed by address. A Rect is 8 bytes: left, top, right, bottom, as signed 16-bit values; right and bottom are excluded (100, 100, 104, 102 covers x 100 to 103 and y 100 to 101).
The pen has a position and a colour; 32,1 puts it back at (0, 0), colour 15, with the clip on the whole screen and a solid pattern. The examples clear the screen, draw, then read the pixels back with 5,33.
32,1 Init Graf Trinity
Resets QuickDraw: clip on the whole screen, pen at (0, 0), colour 15, solid pattern.
Inputs: none.
Outputs: none.
Nothing is drawn or erased. A program may call it at any time to start again from a known state; the examples of this group call it at the start and at the end. The example first moves the pen and changes its colour, then reads the state back with 32,6 and 32,3. NeoBASIC has no keyword for this call.
Firmware documentation text
Toolbox (Trinity, T-12, ADR-01 of the fork). Resets the drawing port : the clip rectangle is the whole screen, the pen is at (0,0) with colour 15. Structures of this group live in 6502 RAM and are passed by address : a Rect is left, top, right, bottom as signed 16 bit values, right and bottom exclusive. Drawing is always clipped to the clip rectangle and goes to the draw page, ignoring the sprite layer.
C (llvm-mos)
/* Remettre QuickDraw dans son état de départ (groupe 32, fonction 1, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static int16_t plume_x, plume_y;
static uint8_t plume_c;
static void get_pen(void) { /* 32,6 Get Pen */
libre();
qd(6);
plume_x = ControlPort.params[0] | ControlPort.params[1] << 8;
plume_y = ControlPort.params[2] | ControlPort.params[3] << 8;
plume_c = ControlPort.params[4];
}
static Rect clip;
static void get_clip(void) { /* 32,3 Get Clip : écrit le rectangle de découpe dans clip */
qd_rect(3, &clip);
}
int main(void) {
couleur(5); /* un état quelconque : plume en (10, 20), couleur 5 */
qd_xy(5, 10, 20);
init_graf(); /* Init Graf */
get_pen();
get_clip();
printf("Plume : %d, %d, couleur %u\n", plume_x, plume_y, plume_c);
printf("Decoupe : %d, %d, %d, %d\n", clip.g, clip.h, clip.d, clip.b);
return 0;
}Plume : 0, 0, couleur 15
Decoupe : 0, 0, 320, 240Mad Pascal
// Remettre QuickDraw dans son état de départ (groupe 32, fonction 1, Trinity).
program qd1;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
var plume_x, plume_y: smallint;
plume_c: byte;
procedure get_pen; // 32,6 Get Pen
begin
NeoWaitMessage;
qd(6);
plume_x := smallint(wordParams[0]);
plume_y := smallint(wordParams[1]);
plume_c := NeoMessage.params[4];
end;
var clip: Rect;
procedure get_clip; // 32,3 Get Clip : écrit le rectangle de découpe dans clip
begin
qd_rect(3, @clip);
end;
begin
couleur(5); // un état quelconque : plume en (10, 20), couleur 5
qd_xy(5, 10, 20);
init_graf; // Init Graf
get_pen;
get_clip;
writeln('Plume : ', plume_x, ', ', plume_y, ', couleur ', plume_c);
writeln('Decoupe : ', clip.g, ', ', clip.h, ', ', clip.d, ', ', clip.b);
end.Plume : 0, 0, couleur 15
Decoupe : 0, 0, 320, 240NeoBASIC
10 ' Remettre QuickDraw dans son etat de depart (groupe 32, fonction 1, Trinity)
20 k = alloc(8)
30 c = 5 : gosub 9300 : x = 10 : y = 20 : f = 5 : gosub 9200 : ' un etat quelconque : plume en (10, 20), couleur 5
40 gosub 9400 : ' Init Graf
50 gosub 9500 : gosub 9600
60 print "Plume : ";px;", ";py;", couleur ";pc
70 print "Decoupe : ";cg;", ";ch;", ";cd;", ";cb
80 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
9500 ' 32,6 Get Pen : px, py, pc
9510 while peek($ff00) : wend : f = 6 : gosub 9110
9520 px = deek($ff04) : py = deek($ff06) : pc = peek($ff08)
9530 if px > 32767 then px = px - 65536
9540 if py > 32767 then py = py - 65536
9550 return
9600 ' 32,3 Get Clip dans le Rect k ; valeurs dans cg, ch, cd, cb
9610 a = k : f = 3 : gosub 9000
9620 cg = deek(k) : ch = deek(k + 2) : cd = deek(k + 4) : cb = deek(k + 6)
9630 returnPlume : 0, 0, couleur 15
Decoupe : 0, 0, 320, 24065C02 assembly (64tass)
; Remettre QuickDraw dans son état de départ (groupe 32, fonction 1, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
; un état quelconque : plume en (10, 20), couleur 5
lda #<b2
ldx #>b2
jsr envoi
lda #<b4
ldx #>b4
jsr envoi
ldx #4
_c3: lda ControlPort+4,x
sta pen,x
dex
bpl _c3
lda #<b5
ldx #>b5
jsr envoi
lda #<t6
ldx #>t6
jsr ecrire
lda pen
ldx pen+1
jsr dec16
lda #<t7
ldx #>t7
jsr ecrire
lda pen+2
ldx pen+2+1
jsr dec16
lda #<t8
ldx #>t8
jsr ecrire
lda pen+4
jsr decimal
lda #13
jsr WriteCharacter
lda #<t9
ldx #>t9
jsr ecrire
lda k
ldx k+1
jsr dec16
lda #<t10
ldx #>t10
jsr ecrire
lda k+2
ldx k+2+1
jsr dec16
lda #<t11
ldx #>t11
jsr ecrire
lda k+4
ldx k+4+1
jsr dec16
lda #<t12
ldx #>t12
jsr ecrire
lda k+6
ldx k+6+1
jsr dec16
lda #13
jsr WriteCharacter
rts
b0: .byte 32, 4, 1, 5 ; 32,4 : Set Pen Colour
b1: .byte 32, 5, 4 ; 32,5 : Move To
.word 10, 20
b2: .byte 32, 1, 0 ; 32,1 : Init Graf
b4: .byte 32, 6, 0 ; 32,6 : Get Pen
pen: .fill 5 ; x, y (16 bits), couleur
b5: .byte 32, 3, 2 ; 32,3 : Get Clip
.word k
k: .fill 8
t6: .text "Plume : ", 0
t7: .text ", ", 0
t8: .text ", couleur ", 0
t9: .text "Decoupe : ", 0
t10: .text ", ", 0
t11: .text ", ", 0
t12: .text ", ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Plume : 0, 0, couleur 15
Decoupe : 0, 0, 320, 24032,2 Set Clip Trinity
Restricts all QuickDraw drawing to the given rectangle, brought back within the screen edges.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of the Rect |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | 1 if the rectangle is inverted (right before left or bottom before top) or outside RAM |
The example sets a zone from 100 to 110, then paints a larger rectangle: only the inside of the zone is painted (pixel (95, 95) stays 0). An inverted rectangle is refused. NeoBASIC has no keyword for this call.
Firmware documentation text
Sets the clip rectangle to the Rect at Parameters:0,1, intersected with the screen. Error if the Rect is inverted or its address is not in RAM.
C (llvm-mos)
/* Limiter le dessin à un rectangle (groupe 32, fonction 2, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static Rect zone = {100, 100, 110, 110}, grand = {90, 90, 120, 120}, envers = {50, 50, 40, 40};
int main(void) {
putchar(12); /* écran effacé : on relit des pixels */
init_graf();
qd_rect(2, &zone); /* Set Clip : rien ne se dessine hors de zone */
couleur(4);
qd_rect(8, &grand); /* 32,8 : peint un rectangle plus grand */
uint8_t dehors = px(95, 95), dedans = px(105, 105);
uint8_t e = qd_rect(2, &envers); /* droite < gauche : refusé */
init_graf(); /* rend tout l'écran au dessin */
printf("Hors de la zone : %u, dedans : %u\n", dehors, dedans);
printf("Rectangle a l'envers : erreur %u\n", e);
return 0;
}Hors de la zone : 0, dedans : 4
Rectangle a l'envers : erreur 1Mad Pascal
// Limiter le dessin à un rectangle (groupe 32, fonction 2, Trinity).
program qd2;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
var zone, grand, envers: Rect;
dehors, dedans, e: byte;
begin
write(chr(12)); // écran effacé : on relit des pixels
zone.g := 100; zone.h := 100; zone.d := 110; zone.b := 110;
grand.g := 90; grand.h := 90; grand.d := 120; grand.b := 120;
envers.g := 50; envers.h := 50; envers.d := 40; envers.b := 40;
init_graf;
qd_rect(2, @zone); // Set Clip : rien ne se dessine hors de zone
couleur(4);
qd_rect(8, @grand); // 32,8 : peint un rectangle plus grand
dehors := NeoGetPixel(95, 95);
dedans := NeoGetPixel(105, 105);
e := qd_rect(2, @envers); // droite < gauche : refusé
init_graf; // rend tout l'écran au dessin
writeln('Hors de la zone : ', dehors, ', dedans : ', dedans);
writeln('Rectangle a l''envers : erreur ', e);
end.Hors de la zone : 0, dedans : 4
Rectangle a l'envers : erreur 1NeoBASIC
10 ' Limiter le dessin a un rectangle (groupe 32, fonction 2, Trinity)
20 cls : ' ecran efface : on relit des pixels
30 z = alloc(8) : q = z : g = 100 : h = 100 : d = 110 : b = 110 : gosub 8000
40 gr = alloc(8) : q = gr : g = 90 : h = 90 : d = 120 : b = 120 : gosub 8000
50 ev = alloc(8) : q = ev : g = 50 : h = 50 : d = 40 : b = 40 : gosub 8000
60 gosub 9400
70 a = z : f = 2 : gosub 9000 : ' Set Clip : rien ne se dessine hors de la zone
80 c = 4 : gosub 9300 : a = gr : f = 8 : gosub 9000 : ' 32,8 : peint un rectangle plus grand
90 de = point(95, 95) : dd = point(105, 105)
100 a = ev : f = 2 : gosub 9000 : e2 = e : ' droite < gauche : refuse
110 gosub 9400 : ' rend tout l'ecran au dessin
120 print "Hors de la zone : ";de;", dedans : ";dd
130 print "Rectangle a l'envers : erreur ";e2
140 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110Hors de la zone : 0, dedans : 4
Rectangle a l'envers : erreur 165C02 assembly (64tass)
; Limiter le dessin à un rectangle (groupe 32, fonction 2, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda #<b2
ldx #>b2
jsr envoi
lda #<b3
ldx #>b3
jsr envoi
lda #95
ldy #95
jsr pixel
sta de
lda #105
ldy #105
jsr pixel
sta dd
lda #<b4
ldx #>b4
jsr envoi
lda ControlPort+2
sta e2
lda #<b5
ldx #>b5
jsr envoi
lda #<t6
ldx #>t6
jsr ecrire
lda de
jsr decimal
lda #<t7
ldx #>t7
jsr ecrire
lda dd
jsr decimal
lda #13
jsr WriteCharacter
lda #<t8
ldx #>t8
jsr ecrire
lda e2
jsr decimal
lda #13
jsr WriteCharacter
rts
; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : X
stz ControlPort+5
sty ControlPort+6 ; P2-P3 : Y
stz ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
z: .word 100, 100, 110, 110 ; gauche, haut, droite, bas (droite et bas exclus)
gr: .word 90, 90, 120, 120 ; gauche, haut, droite, bas (droite et bas exclus)
ev: .word 50, 50, 40, 40 ; gauche, haut, droite, bas (droite et bas exclus)
b0: .byte 32, 1, 0 ; 32,1 : Init Graf
b1: .byte 32, 2, 2 ; 32,2 : Set Clip, rien ne se dessine hors de la zone
.word z
b2: .byte 32, 4, 1, 4 ; 32,4 : Set Pen Colour
b3: .byte 32, 8, 2 ; 32,8 : peint un rectangle plus grand
.word gr
de: .byte 0
dd: .byte 0
b4: .byte 32, 2, 2 ; droite < gauche : refusé
.word ev
e2: .byte 0
b5: .byte 32, 1, 0 ; rend tout l'écran au dessin
t6: .text "Hors de la zone : ", 0
t7: .text ", dedans : ", 0
t8: .text "Rectangle a l'envers : erreur ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Hors de la zone : 0, dedans : 4
Rectangle a l'envers : erreur 132,3 Get Clip Trinity
Writes the current clip rectangle into the given Rect.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of the Rect to fill |
Outputs: none.
The clip read back is the one really in force: 32,2 has intersected it with the screen. The example asks for -10, -10, 500, 50 and reads back 0, 0, 320, 50. NeoBASIC has no keyword for this call.
Firmware documentation text
Writes the current clip rectangle into the Rect at Parameters:0,1.
C (llvm-mos)
/* Relire le rectangle de découpe (groupe 32, fonction 3, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static Rect clip;
static void get_clip(void) { /* 32,3 Get Clip : écrit le rectangle de découpe dans clip */
qd_rect(3, &clip);
}
static Rect demande = {-10, -10, 500, 50};
int main(void) {
init_graf();
qd_rect(2, &demande); /* 32,2 : déborde de l'écran à gauche, en haut et à droite */
get_clip(); /* Get Clip */
init_graf();
printf("Decoupe : %d, %d, %d, %d\n", clip.g, clip.h, clip.d, clip.b);
return 0;
}Decoupe : 0, 0, 320, 50Mad Pascal
// Relire le rectangle de découpe (groupe 32, fonction 3, Trinity).
program qd3;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
var clip: Rect;
procedure get_clip; // 32,3 Get Clip : écrit le rectangle de découpe dans clip
begin
qd_rect(3, @clip);
end;
var demande: Rect;
begin
demande.g := -10; demande.h := -10; demande.d := 500; demande.b := 50;
init_graf;
qd_rect(2, @demande); // 32,2 : déborde de l'écran à gauche, en haut et à droite
get_clip; // Get Clip
init_graf;
writeln('Decoupe : ', clip.g, ', ', clip.h, ', ', clip.d, ', ', clip.b);
end.Decoupe : 0, 0, 320, 50NeoBASIC
10 ' Relire le rectangle de decoupe (groupe 32, fonction 3, Trinity)
20 k = alloc(8) : q = alloc(8) : g = -10 : h = -10 : d = 500 : b = 50 : gosub 8000
30 gosub 9400
40 a = q : f = 2 : gosub 9000 : ' 32,2 : deborde de l'ecran a gauche, en haut et a droite
50 gosub 9600 : ' Get Clip
60 gosub 9400
70 print "Decoupe : ";cg;", ";ch;", ";cd;", ";cb
80 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
9600 ' 32,3 Get Clip dans le Rect k ; valeurs dans cg, ch, cd, cb
9610 a = k : f = 3 : gosub 9000
9620 cg = deek(k) : ch = deek(k + 2) : cd = deek(k + 4) : cb = deek(k + 6)
9630 returnDecoupe : 0, 0, 320, 5065C02 assembly (64tass)
; Relire le rectangle de découpe (groupe 32, fonction 3, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda #<b2
ldx #>b2
jsr envoi
lda #<b3
ldx #>b3
jsr envoi
lda #<t4
ldx #>t4
jsr ecrire
lda k
ldx k+1
jsr dec16
lda #<t5
ldx #>t5
jsr ecrire
lda k+2
ldx k+2+1
jsr dec16
lda #<t6
ldx #>t6
jsr ecrire
lda k+4
ldx k+4+1
jsr dec16
lda #<t7
ldx #>t7
jsr ecrire
lda k+6
ldx k+6+1
jsr dec16
lda #13
jsr WriteCharacter
rts
q: .word 65526, 65526, 500, 50 ; gauche, haut, droite, bas (droite et bas exclus)
k: .fill 8
b0: .byte 32, 1, 0 ; 32,1 : Init Graf
b1: .byte 32, 2, 2 ; 32,2 : déborde de l'écran à gauche, en haut et à droite
.word q
b2: .byte 32, 3, 2 ; Get Clip
.word k
b3: .byte 32, 1, 0 ; 32,1 : Init Graf
t4: .text "Decoupe : ", 0
t5: .text ", ", 0
t6: .text ", ", 0
t7: .text ", ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Decoupe : 0, 0, 320, 5032,4 Set Pen Colour Trinity
Selects the pen colour (palette index), used by 32,7, 32,8, 32,11, 32,13 and 32,16.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | colour (palette index) |
Outputs: none.
The example selects colour 9, paints a rectangle, then reads back a pixel and the pen (32,6). NeoBASIC has no keyword for this call.
Firmware documentation text
Sets the pen colour (palette index) used by Frame Rect and Paint Rect to Parameter:0.
C (llvm-mos)
/* Choisir la couleur de la plume (groupe 32, fonction 4, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static int16_t plume_x, plume_y;
static uint8_t plume_c;
static void get_pen(void) { /* 32,6 Get Pen */
libre();
qd(6);
plume_x = ControlPort.params[0] | ControlPort.params[1] << 8;
plume_y = ControlPort.params[2] | ControlPort.params[3] << 8;
plume_c = ControlPort.params[4];
}
static Rect r = {100, 100, 104, 104};
int main(void) {
putchar(12);
init_graf();
couleur(9); /* Set Pen Colour */
qd_rect(8, &r); /* 32,8 peint dans cette couleur */
uint8_t p = px(101, 101);
get_pen();
init_graf();
printf("Pixel : %u, plume : %u\n", p, plume_c);
return 0;
}Pixel : 9, plume : 9Mad Pascal
// Choisir la couleur de la plume (groupe 32, fonction 4, Trinity).
program qd4;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
var plume_x, plume_y: smallint;
plume_c: byte;
procedure get_pen; // 32,6 Get Pen
begin
NeoWaitMessage;
qd(6);
plume_x := smallint(wordParams[0]);
plume_y := smallint(wordParams[1]);
plume_c := NeoMessage.params[4];
end;
var r: Rect;
p: byte;
begin
write(chr(12));
r.g := 100; r.h := 100; r.d := 104; r.b := 104;
init_graf;
couleur(9); // Set Pen Colour
qd_rect(8, @r); // 32,8 peint dans cette couleur
p := NeoGetPixel(101, 101);
get_pen;
init_graf;
writeln('Pixel : ', p, ', plume : ', plume_c);
end.Pixel : 9, plume : 9NeoBASIC
10 ' Choisir la couleur de la plume (groupe 32, fonction 4, Trinity)
20 cls : q = alloc(8) : g = 100 : h = 100 : d = 104 : b = 104 : gosub 8000
30 gosub 9400
40 c = 9 : gosub 9300 : ' Set Pen Colour
50 a = q : f = 8 : gosub 9000 : ' 32,8 peint dans cette couleur
60 p = point(101, 101) : gosub 9500
70 gosub 9400
80 print "Pixel : ";p;", plume : ";pc
90 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
9500 ' 32,6 Get Pen : px, py, pc
9510 while peek($ff00) : wend : f = 6 : gosub 9110
9520 px = deek($ff04) : py = deek($ff06) : pc = peek($ff08)
9530 if px > 32767 then px = px - 65536
9540 if py > 32767 then py = py - 65536
9550 returnPixel : 9, plume : 965C02 assembly (64tass)
; Choisir la couleur de la plume (groupe 32, fonction 4, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda #<b2
ldx #>b2
jsr envoi
lda #101
ldy #101
jsr pixel
sta px
lda #<b4
ldx #>b4
jsr envoi
ldx #4
_c3: lda ControlPort+4,x
sta pen,x
dex
bpl _c3
lda #<b5
ldx #>b5
jsr envoi
lda #<t6
ldx #>t6
jsr ecrire
lda px
jsr decimal
lda #<t7
ldx #>t7
jsr ecrire
lda pen+4
jsr decimal
lda #13
jsr WriteCharacter
rts
; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : X
stz ControlPort+5
sty ControlPort+6 ; P2-P3 : Y
stz ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
q: .word 100, 100, 104, 104 ; gauche, haut, droite, bas (droite et bas exclus)
b0: .byte 32, 1, 0 ; 32,1 : Init Graf
b1: .byte 32, 4, 1, 9 ; Set Pen Colour
b2: .byte 32, 8, 2 ; 32,8 peint dans cette couleur
.word q
px: .byte 0
b4: .byte 32, 6, 0 ; 32,6 : Get Pen
pen: .fill 5 ; x, y (16 bits), couleur
b5: .byte 32, 1, 0 ; 32,1 : Init Graf
t6: .text "Pixel : ", 0
t7: .text ", plume : ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Pixel : 9, plume : 932,5 Move To Trinity
Moves the pen without drawing anything.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | int16 | X (signed) |
P2-P3 | int16 | Y (signed) |
Outputs: none.
The example puts the pen at (30, 40): the pixel stays 0; the line of 32,11 then starts from there. NeoBASIC has no keyword for this call.
Firmware documentation text
Moves the pen to Parameters:0,1 (X) and Parameters:2,3 (Y), signed 16 bit, without drawing.
C (llvm-mos)
/* Déplacer la plume sans dessiner (groupe 32, fonction 5, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static int16_t plume_x, plume_y;
static uint8_t plume_c;
static void get_pen(void) { /* 32,6 Get Pen */
libre();
qd(6);
plume_x = ControlPort.params[0] | ControlPort.params[1] << 8;
plume_y = ControlPort.params[2] | ControlPort.params[3] << 8;
plume_c = ControlPort.params[4];
}
int main(void) {
putchar(12);
init_graf();
qd_xy(5, 30, 40); /* Move To : rien n'est dessiné */
get_pen();
int16_t x = plume_x, y = plume_y;
uint8_t avant = px(30, 40);
qd_xy(11, 60, 40); /* 32,11 : trait depuis la plume */
uint8_t trait = px(45, 40);
init_graf();
printf("Plume : %d, %d ; pixel %u, puis trait : %u\n", x, y, avant, trait);
return 0;
}Plume : 30, 40 ; pixel 0, puis trait : 15Mad Pascal
// Déplacer la plume sans dessiner (groupe 32, fonction 5, Trinity).
program qd5;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
var plume_x, plume_y: smallint;
plume_c: byte;
procedure get_pen; // 32,6 Get Pen
begin
NeoWaitMessage;
qd(6);
plume_x := smallint(wordParams[0]);
plume_y := smallint(wordParams[1]);
plume_c := NeoMessage.params[4];
end;
var x, y: smallint;
avant, trait: byte;
begin
write(chr(12));
init_graf;
qd_xy(5, 30, 40); // Move To : rien n'est dessiné
get_pen;
x := plume_x;
y := plume_y;
avant := NeoGetPixel(30, 40);
qd_xy(11, 60, 40); // 32,11 : trait depuis la plume
trait := NeoGetPixel(45, 40);
init_graf;
writeln('Plume : ', x, ', ', y, ' ; pixel ', avant, ', puis trait : ', trait);
end.Plume : 30, 40 ; pixel 0, puis trait : 15NeoBASIC
10 ' Deplacer la plume sans dessiner (groupe 32, fonction 5, Trinity)
20 cls : gosub 9400
30 x = 30 : y = 40 : f = 5 : gosub 9200 : ' Move To : rien n'est dessine
40 gosub 9500 : xx = px : yy = py : av = point(30, 40)
50 x = 60 : y = 40 : f = 11 : gosub 9200 : ' 32,11 : trait depuis la plume
60 tr = point(45, 40)
70 gosub 9400
80 print "Plume : ";xx;", ";yy;" ; pixel ";av;", puis trait : ";tr
90 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
9500 ' 32,6 Get Pen : px, py, pc
9510 while peek($ff00) : wend : f = 6 : gosub 9110
9520 px = deek($ff04) : py = deek($ff06) : pc = peek($ff08)
9530 if px > 32767 then px = px - 65536
9540 if py > 32767 then py = py - 65536
9550 returnPlume : 30, 40 ; pixel 0, puis trait : 1565C02 assembly (64tass)
; Déplacer la plume sans dessiner (groupe 32, fonction 5, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda #<b3
ldx #>b3
jsr envoi
ldx #4
_c2: lda ControlPort+4,x
sta pen,x
dex
bpl _c2
lda #30
ldy #40
jsr pixel
sta av
lda #<b4
ldx #>b4
jsr envoi
lda #45
ldy #40
jsr pixel
sta tr
lda #<b5
ldx #>b5
jsr envoi
lda #<t6
ldx #>t6
jsr ecrire
lda pen
ldx pen+1
jsr dec16
lda #<t7
ldx #>t7
jsr ecrire
lda pen+2
ldx pen+2+1
jsr dec16
lda #<t8
ldx #>t8
jsr ecrire
lda av
jsr decimal
lda #<t9
ldx #>t9
jsr ecrire
lda tr
jsr decimal
lda #13
jsr WriteCharacter
rts
; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : X
stz ControlPort+5
sty ControlPort+6 ; P2-P3 : Y
stz ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
b0: .byte 32, 1, 0 ; 32,1 : Init Graf
b1: .byte 32, 5, 4 ; Move To : rien n'est dessiné
.word 30, 40
b3: .byte 32, 6, 0 ; 32,6 : Get Pen
pen: .fill 5 ; x, y (16 bits), couleur
av: .byte 0
b4: .byte 32, 11, 4 ; 32,11 : Line To
.word 60, 40
tr: .byte 0
b5: .byte 32, 1, 0 ; 32,1 : Init Graf
t6: .text "Plume : ", 0
t7: .text ", ", 0
t8: .text " ; pixel ", 0
t9: .text ", puis trait : ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Plume : 30, 40 ; pixel 0, puis trait : 1532,6 Get Pen Trinity
Returns the pen position and colour.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | int16 | pen X |
P2-P3 | int16 | pen Y |
P4 | uint8 | pen colour |
After 32,11, the pen is at the end of the line: the example draws from (10, 50) to (70, 50) in colour 3. NeoBASIC has no keyword for this call.
Firmware documentation text
Returns the pen position in Parameters:0,1 (X) and Parameters:2,3 (Y) and the pen colour in Parameter:4.
C (llvm-mos)
/* Lire la position et la couleur de la plume (groupe 32, fonction 6, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static int16_t plume_x, plume_y;
static uint8_t plume_c;
static void get_pen(void) { /* 32,6 Get Pen */
libre();
qd(6);
plume_x = ControlPort.params[0] | ControlPort.params[1] << 8;
plume_y = ControlPort.params[2] | ControlPort.params[3] << 8;
plume_c = ControlPort.params[4];
}
int main(void) {
putchar(12);
init_graf();
couleur(3);
qd_xy(5, 10, 50);
qd_xy(11, 70, 50); /* 32,11 : la plume finit au bout du trait */
get_pen(); /* Get Pen */
init_graf();
printf("Plume : %d, %d, couleur %u\n", plume_x, plume_y, plume_c);
return 0;
}Plume : 70, 50, couleur 3Mad Pascal
// Lire la position et la couleur de la plume (groupe 32, fonction 6, Trinity).
program qd6;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
var plume_x, plume_y: smallint;
plume_c: byte;
procedure get_pen; // 32,6 Get Pen
begin
NeoWaitMessage;
qd(6);
plume_x := smallint(wordParams[0]);
plume_y := smallint(wordParams[1]);
plume_c := NeoMessage.params[4];
end;
begin
write(chr(12));
init_graf;
couleur(3);
qd_xy(5, 10, 50);
qd_xy(11, 70, 50); // 32,11 : la plume finit au bout du trait
get_pen; // Get Pen
init_graf;
writeln('Plume : ', plume_x, ', ', plume_y, ', couleur ', plume_c);
end.Plume : 70, 50, couleur 3NeoBASIC
10 ' Lire la position et la couleur de la plume (groupe 32, fonction 6, Trinity)
20 cls : gosub 9400
30 c = 3 : gosub 9300
40 x = 10 : y = 50 : f = 5 : gosub 9200
50 x = 70 : y = 50 : f = 11 : gosub 9200 : ' 32,11 : la plume finit au bout du trait
60 gosub 9500 : ' Get Pen
70 gosub 9400
80 print "Plume : ";px;", ";py;", couleur ";pc
90 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
9500 ' 32,6 Get Pen : px, py, pc
9510 while peek($ff00) : wend : f = 6 : gosub 9110
9520 px = deek($ff04) : py = deek($ff06) : pc = peek($ff08)
9530 if px > 32767 then px = px - 65536
9540 if py > 32767 then py = py - 65536
9550 returnPlume : 70, 50, couleur 365C02 assembly (64tass)
; Lire la position et la couleur de la plume (groupe 32, fonction 6, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda #<b2
ldx #>b2
jsr envoi
lda #<b3
ldx #>b3
jsr envoi
lda #<b4
ldx #>b4
jsr envoi
ldx #4
_cp: lda ControlPort+4,x
sta pen,x
dex
bpl _cp
lda #<b5
ldx #>b5
jsr envoi
lda #<t6
ldx #>t6
jsr ecrire
lda pen
ldx pen+1
jsr dec16
lda #<t7
ldx #>t7
jsr ecrire
lda pen+2
ldx pen+2+1
jsr dec16
lda #<t8
ldx #>t8
jsr ecrire
lda pen+4
jsr decimal
lda #13
jsr WriteCharacter
rts
b0: .byte 32, 1, 0 ; 32,1 : Init Graf
b1: .byte 32, 4, 1, 3 ; 32,4 : Set Pen Colour
b2: .byte 32, 5, 4 ; 32,5 : Move To
.word 10, 50
b3: .byte 32, 11, 4 ; 32,11 : la plume finit au bout du trait
.word 70, 50
b4: .byte 32, 6, 0 ; Get Pen
pen: .fill 5 ; x, y (16 bits), couleur
b5: .byte 32, 1, 0 ; 32,1 : Init Graf
t6: .text "Plume : ", 0
t7: .text ", ", 0
t8: .text ", couleur ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Plume : 70, 50, couleur 332,7 Frame Rect Trinity
Draws the one-pixel outline of a rectangle in the pen colour.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of the Rect |
Outputs: none.
The outline is inside the rectangle: for 100, 100, 120, 110, the corners are at (100, 100) and (119, 109), and pixel (120, 100) stays empty. The inside is not touched. NeoBASIC has no keyword for this call.
Firmware documentation text
Draws the one pixel outline of the Rect at Parameters:0,1 in the pen colour, inside the rectangle, clipped.
C (llvm-mos)
/* Tracer le contour d'un rectangle (groupe 32, fonction 7, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static Rect r = {100, 100, 120, 110};
int main(void) {
putchar(12);
init_graf();
couleur(6);
qd_rect(7, &r); /* Frame Rect */
uint8_t a = px(100, 100), b = px(119, 109); /* coins : le contour est à l'intérieur */
uint8_t c = px(120, 100), d = px(110, 105); /* juste à droite, et au milieu */
init_graf();
printf("Coins : %u %u, a droite : %u, au milieu : %u\n", a, b, c, d);
return 0;
}Coins : 6 6, a droite : 0, au milieu : 0Mad Pascal
// Tracer le contour d'un rectangle (groupe 32, fonction 7, Trinity).
program qd7;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
var r: Rect;
a, b, c, d: byte;
begin
write(chr(12));
r.g := 100; r.h := 100; r.d := 120; r.b := 110;
init_graf;
couleur(6);
qd_rect(7, @r); // Frame Rect
a := NeoGetPixel(100, 100); // coins : le contour est à l'intérieur
b := NeoGetPixel(119, 109);
c := NeoGetPixel(120, 100); // juste à droite, et au milieu
d := NeoGetPixel(110, 105);
init_graf;
writeln('Coins : ', a, ' ', b, ', a droite : ', c, ', au milieu : ', d);
end.Coins : 6 6, a droite : 0, au milieu : 0NeoBASIC
10 ' Tracer le contour d'un rectangle (groupe 32, fonction 7, Trinity)
20 cls : q = alloc(8) : g = 100 : h = 100 : d = 120 : b = 110 : gosub 8000
30 gosub 9400 : c = 6 : gosub 9300
40 a = q : f = 7 : gosub 9000 : ' Frame Rect
50 c1 = point(100, 100) : c2 = point(119, 109) : ' coins : le contour est a l'interieur
60 dr = point(120, 100) : mi = point(110, 105) : ' juste a droite, et au milieu
70 gosub 9400
80 print "Coins : ";c1;" ";c2;", a droite : ";dr;", au milieu : ";mi
90 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110Coins : 6 6, a droite : 0, au milieu : 065C02 assembly (64tass)
; Tracer le contour d'un rectangle (groupe 32, fonction 7, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda #<b2
ldx #>b2
jsr envoi
lda #100
ldy #100
jsr pixel
sta c1
lda #119
ldy #109
jsr pixel
sta c2
lda #120
ldy #100
jsr pixel
sta dr
lda #110
ldy #105
jsr pixel
sta mi
lda #<b3
ldx #>b3
jsr envoi
lda #<t4
ldx #>t4
jsr ecrire
lda c1
jsr decimal
lda #<t5
ldx #>t5
jsr ecrire
lda c2
jsr decimal
lda #<t6
ldx #>t6
jsr ecrire
lda dr
jsr decimal
lda #<t7
ldx #>t7
jsr ecrire
lda mi
jsr decimal
lda #13
jsr WriteCharacter
rts
; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : X
stz ControlPort+5
sty ControlPort+6 ; P2-P3 : Y
stz ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
q: .word 100, 100, 120, 110 ; gauche, haut, droite, bas (droite et bas exclus)
b0: .byte 32, 1, 0 ; 32,1 : Init Graf
b1: .byte 32, 4, 1, 6 ; 32,4 : Set Pen Colour
b2: .byte 32, 7, 2 ; Frame Rect
.word q
c1: .byte 0
c2: .byte 0
dr: .byte 0
mi: .byte 0
b3: .byte 32, 1, 0 ; 32,1 : Init Graf
t4: .text "Coins : ", 0
t5: .text " ", 0
t6: .text ", a droite : ", 0
t7: .text ", au milieu : ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Coins : 6 6, a droite : 0, au milieu : 032,8 Paint Rect Trinity
Paints a rectangle in the pen colour.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of the Rect |
Outputs: none.
The right and bottom edges are excluded: 100, 100, 104, 102 paints x 100 to 103 on lines 100 and 101. The pattern of 32,12 is not used (32,13 uses it). NeoBASIC has no keyword for this call.
Firmware documentation text
Fills the Rect at Parameters:0,1 with the pen colour, clipped.
C (llvm-mos)
/* Peindre un rectangle (groupe 32, fonction 8, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static Rect r = {100, 100, 104, 102};
int main(void) {
putchar(12);
init_graf();
couleur(5);
qd_rect(8, &r); /* Paint Rect : x 100 à 103, y 100 et 101 */
uint8_t a = px(100, 100), b = px(103, 101), c = px(104, 101), d = px(103, 102);
init_graf();
printf("Dedans : %u %u, droite : %u, bas : %u\n", a, b, c, d);
return 0;
}Dedans : 5 5, droite : 0, bas : 0Mad Pascal
// Peindre un rectangle (groupe 32, fonction 8, Trinity).
program qd8;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
var r: Rect;
a, b, c, d: byte;
begin
write(chr(12));
r.g := 100; r.h := 100; r.d := 104; r.b := 102;
init_graf;
couleur(5);
qd_rect(8, @r); // Paint Rect : x 100 à 103, y 100 et 101
a := NeoGetPixel(100, 100);
b := NeoGetPixel(103, 101);
c := NeoGetPixel(104, 101);
d := NeoGetPixel(103, 102);
init_graf;
writeln('Dedans : ', a, ' ', b, ', droite : ', c, ', bas : ', d);
end.Dedans : 5 5, droite : 0, bas : 0NeoBASIC
10 ' Peindre un rectangle (groupe 32, fonction 8, Trinity)
20 cls : q = alloc(8) : g = 100 : h = 100 : d = 104 : b = 102 : gosub 8000
30 gosub 9400 : c = 5 : gosub 9300
40 a = q : f = 8 : gosub 9000 : ' Paint Rect : x 100 a 103, y 100 et 101
50 p1 = point(100, 100) : p2 = point(103, 101) : p3 = point(104, 101) : p4 = point(103, 102)
60 gosub 9400
70 print "Dedans : ";p1;" ";p2;", droite : ";p3;", bas : ";p4
80 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110Dedans : 5 5, droite : 0, bas : 065C02 assembly (64tass)
; Peindre un rectangle (groupe 32, fonction 8, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda #<b2
ldx #>b2
jsr envoi
lda #100
ldy #100
jsr pixel
sta p1
lda #103
ldy #101
jsr pixel
sta p2
lda #104
ldy #101
jsr pixel
sta p3
lda #103
ldy #102
jsr pixel
sta p4
lda #<b3
ldx #>b3
jsr envoi
lda #<t4
ldx #>t4
jsr ecrire
lda p1
jsr decimal
lda #<t5
ldx #>t5
jsr ecrire
lda p2
jsr decimal
lda #<t6
ldx #>t6
jsr ecrire
lda p3
jsr decimal
lda #<t7
ldx #>t7
jsr ecrire
lda p4
jsr decimal
lda #13
jsr WriteCharacter
rts
; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : X
stz ControlPort+5
sty ControlPort+6 ; P2-P3 : Y
stz ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
q: .word 100, 100, 104, 102 ; gauche, haut, droite, bas (droite et bas exclus)
b0: .byte 32, 1, 0 ; 32,1 : Init Graf
b1: .byte 32, 4, 1, 5 ; 32,4 : Set Pen Colour
b2: .byte 32, 8, 2 ; Paint Rect : x 100 à 103, y 100 et 101
.word q
p1: .byte 0
p2: .byte 0
p3: .byte 0
p4: .byte 0
b3: .byte 32, 1, 0 ; 32,1 : Init Graf
t4: .text "Dedans : ", 0
t5: .text " ", 0
t6: .text ", droite : ", 0
t7: .text ", bas : ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Dedans : 5 5, droite : 0, bas : 032,9 Erase Rect Trinity
Fills a rectangle with a given background colour.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of the Rect |
P2 | uint8 | background colour |
Outputs: none.
The pen colour is not changed. The example paints a square in colour 4, then erases its centre in colour 2. NeoBASIC has no keyword for this call.
Firmware documentation text
Fills the Rect at Parameters:0,1 with the colour in Parameter:2 (the background), clipped.
C (llvm-mos)
/* Effacer un rectangle avec une couleur de fond (groupe 32, fonction 9, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static Rect r = {100, 100, 110, 110}, petit = {102, 102, 106, 106};
int main(void) {
putchar(12);
init_graf();
couleur(4);
qd_rect(8, &r); /* 32,8 : un carré de couleur 4 */
libre();
ControlPort.params[0] = (uint16_t)&petit & 0xFF;
ControlPort.params[1] = (uint16_t)&petit >> 8;
ControlPort.params[2] = 2; /* P2 : couleur du fond */
qd(9); /* Erase Rect */
uint8_t a = px(103, 103), b = px(100, 100);
init_graf();
printf("Efface : %u, autour : %u\n", a, b);
return 0;
}Efface : 2, autour : 4Mad Pascal
// Effacer un rectangle avec une couleur de fond (groupe 32, fonction 9, Trinity).
program qd9;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
var r, petit: Rect;
a, b: byte;
begin
write(chr(12));
r.g := 100; r.h := 100; r.d := 110; r.b := 110;
petit.g := 102; petit.h := 102; petit.d := 106; petit.b := 106;
init_graf;
couleur(4);
qd_rect(8, @r); // 32,8 : un carré de couleur 4
NeoWaitMessage;
wordParams[0] := word(@petit);
NeoMessage.params[2] := 2; // P2 : couleur du fond
qd(9); // Erase Rect
a := NeoGetPixel(103, 103);
b := NeoGetPixel(100, 100);
init_graf;
writeln('Efface : ', a, ', autour : ', b);
end.Efface : 2, autour : 4NeoBASIC
10 ' Effacer un rectangle avec une couleur de fond (groupe 32, fonction 9, Trinity)
20 cls : r = alloc(8) : q = r : g = 100 : h = 100 : d = 110 : b = 110 : gosub 8000
30 pe = alloc(8) : q = pe : g = 102 : h = 102 : d = 106 : b = 106 : gosub 8000
40 gosub 9400 : c = 4 : gosub 9300
50 a = r : f = 8 : gosub 9000 : ' 32,8 : un carre de couleur 4
60 while peek($ff00) : wend : doke $ff04, pe : poke $ff06, 2 : f = 9 : gosub 9110 : ' Erase Rect, P2 : couleur du fond
70 p1 = point(103, 103) : p2 = point(100, 100)
80 gosub 9400
90 print "Efface : ";p1;", autour : ";p2
100 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110Efface : 2, autour : 465C02 assembly (64tass)
; Effacer un rectangle avec une couleur de fond (groupe 32, fonction 9, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda #<b2
ldx #>b2
jsr envoi
lda #<b3
ldx #>b3
jsr envoi
lda #103
ldy #103
jsr pixel
sta p1
lda #100
ldy #100
jsr pixel
sta p2
lda #<b4
ldx #>b4
jsr envoi
lda #<t5
ldx #>t5
jsr ecrire
lda p1
jsr decimal
lda #<t6
ldx #>t6
jsr ecrire
lda p2
jsr decimal
lda #13
jsr WriteCharacter
rts
; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : X
stz ControlPort+5
sty ControlPort+6 ; P2-P3 : Y
stz ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
r: .word 100, 100, 110, 110 ; gauche, haut, droite, bas (droite et bas exclus)
pe: .word 102, 102, 106, 106 ; gauche, haut, droite, bas (droite et bas exclus)
b0: .byte 32, 1, 0 ; 32,1 : Init Graf
b1: .byte 32, 4, 1, 4 ; 32,4 : Set Pen Colour
b2: .byte 32, 8, 2 ; 32,8 : un carré de couleur 4
.word r
b3: .byte 32, 9, 3 ; Erase Rect, P2 : couleur du fond
.word pe
.byte 2
p1: .byte 0
p2: .byte 0
b4: .byte 32, 1, 0 ; 32,1 : Init Graf
t5: .text "Efface : ", 0
t6: .text ", autour : ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Efface : 2, autour : 432,10 Invert Rect Trinity
Inverts the pixels of a rectangle.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of the Rect |
Outputs: none.
In mode 0, each colour index is exclusive-ORed with $FF: 5 becomes 250. A second inversion gives back the starting image. Depending on the mode, Trinity uses $0F or 1 instead of $FF. NeoBASIC has no keyword for this call.
Firmware documentation text
Inverts every pixel of the Rect at Parameters:0,1 (colour index XOR $FF, $0F or 1 depending on the mode), clipped.
C (llvm-mos)
/* Inverser les pixels d'un rectangle (groupe 32, fonction 10, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static Rect r = {100, 100, 104, 104};
int main(void) {
putchar(12);
init_graf();
couleur(5);
qd_rect(8, &r);
qd_rect(10, &r); /* Invert Rect : en mode 0, XOR $FF */
uint8_t a = px(101, 101);
qd_rect(10, &r); /* deux fois : retour au départ */
uint8_t b = px(101, 101);
init_graf();
printf("Inverse : %u, deux fois : %u\n", a, b);
return 0;
}Inverse : 250, deux fois : 5Mad Pascal
// Inverser les pixels d'un rectangle (groupe 32, fonction 10, Trinity).
program qd10;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
var r: Rect;
a, b: byte;
begin
write(chr(12));
r.g := 100; r.h := 100; r.d := 104; r.b := 104;
init_graf;
couleur(5);
qd_rect(8, @r);
qd_rect(10, @r); // Invert Rect : en mode 0, XOR $FF
a := NeoGetPixel(101, 101);
qd_rect(10, @r); // deux fois : retour au départ
b := NeoGetPixel(101, 101);
init_graf;
writeln('Inverse : ', a, ', deux fois : ', b);
end.Inverse : 250, deux fois : 5NeoBASIC
10 ' Inverser les pixels d'un rectangle (groupe 32, fonction 10, Trinity)
20 cls : q = alloc(8) : g = 100 : h = 100 : d = 104 : b = 104 : gosub 8000
30 gosub 9400 : c = 5 : gosub 9300
40 a = q : f = 8 : gosub 9000
50 f = 10 : gosub 9000 : p1 = point(101, 101) : ' Invert Rect : en mode 0, XOR $FF
60 f = 10 : gosub 9000 : p2 = point(101, 101) : ' deux fois : retour au depart
70 gosub 9400
80 print "Inverse : ";p1;", deux fois : ";p2
90 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110Inverse : 250, deux fois : 565C02 assembly (64tass)
; Inverser les pixels d'un rectangle (groupe 32, fonction 10, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda #<b2
ldx #>b2
jsr envoi
lda #<b3
ldx #>b3
jsr envoi
lda #101
ldy #101
jsr pixel
sta p1
lda #<b4
ldx #>b4
jsr envoi
lda #101
ldy #101
jsr pixel
sta p2
lda #<b5
ldx #>b5
jsr envoi
lda #<t6
ldx #>t6
jsr ecrire
lda p1
jsr decimal
lda #<t7
ldx #>t7
jsr ecrire
lda p2
jsr decimal
lda #13
jsr WriteCharacter
rts
; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : X
stz ControlPort+5
sty ControlPort+6 ; P2-P3 : Y
stz ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
q: .word 100, 100, 104, 104 ; gauche, haut, droite, bas (droite et bas exclus)
b0: .byte 32, 1, 0 ; 32,1 : Init Graf
b1: .byte 32, 4, 1, 5 ; 32,4 : Set Pen Colour
b2: .byte 32, 8, 2 ; 32,8
.word q
b3: .byte 32, 10, 2 ; Invert Rect : en mode 0, XOR $FF
.word q
p1: .byte 0
b4: .byte 32, 10, 2 ; deux fois : retour au départ
.word q
p2: .byte 0
b5: .byte 32, 1, 0 ; 32,1 : Init Graf
t6: .text "Inverse : ", 0
t7: .text ", deux fois : ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Inverse : 250, deux fois : 532,11 Line To Trinity
Draws a line from the pen to the given point, in the pen colour, and moves the pen there.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | int16 | end X (signed) |
P2-P3 | int16 | end Y (signed) |
Outputs: none.
Both the start point and the end point are drawn, but not the next pixel. NeoBASIC has no keyword for this call.
Firmware documentation text
Draws a line from the pen to Parameters:0,1 (X) and Parameters:2,3 (Y) in the pen colour, clipped, and moves the pen there.
C (llvm-mos)
/* Tracer un trait depuis la plume (groupe 32, fonction 11, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
int main(void) {
putchar(12);
init_graf();
couleur(7);
qd_xy(5, 50, 60); /* 32,5 : départ */
qd_xy(11, 60, 60); /* Line To : le point d'arrivée est tracé */
uint8_t a = px(50, 60), b = px(60, 60), c = px(61, 60);
init_graf();
printf("Depart : %u, arrivee : %u, apres : %u\n", a, b, c);
return 0;
}Depart : 7, arrivee : 7, apres : 0Mad Pascal
// Tracer un trait depuis la plume (groupe 32, fonction 11, Trinity).
program qd11;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
var a, b, c: byte;
begin
write(chr(12));
init_graf;
couleur(7);
qd_xy(5, 50, 60); // 32,5 : départ
qd_xy(11, 60, 60); // Line To : le point d'arrivée est tracé
a := NeoGetPixel(50, 60);
b := NeoGetPixel(60, 60);
c := NeoGetPixel(61, 60);
init_graf;
writeln('Depart : ', a, ', arrivee : ', b, ', apres : ', c);
end.Depart : 7, arrivee : 7, apres : 0NeoBASIC
10 ' Tracer un trait depuis la plume (groupe 32, fonction 11, Trinity)
20 cls : gosub 9400 : c = 7 : gosub 9300
30 x = 50 : y = 60 : f = 5 : gosub 9200 : ' 32,5 : depart
40 x = 60 : y = 60 : f = 11 : gosub 9200 : ' Line To : le point d'arrivee est trace
50 p1 = point(50, 60) : p2 = point(60, 60) : p3 = point(61, 60)
60 gosub 9400
70 print "Depart : ";p1;", arrivee : ";p2;", apres : ";p3
80 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110Depart : 7, arrivee : 7, apres : 065C02 assembly (64tass)
; Tracer un trait depuis la plume (groupe 32, fonction 11, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda #<b2
ldx #>b2
jsr envoi
lda #<b3
ldx #>b3
jsr envoi
lda #50
ldy #60
jsr pixel
sta p1
lda #60
ldy #60
jsr pixel
sta p2
lda #61
ldy #60
jsr pixel
sta p3
lda #<b4
ldx #>b4
jsr envoi
lda #<t5
ldx #>t5
jsr ecrire
lda p1
jsr decimal
lda #<t6
ldx #>t6
jsr ecrire
lda p2
jsr decimal
lda #<t7
ldx #>t7
jsr ecrire
lda p3
jsr decimal
lda #13
jsr WriteCharacter
rts
; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : X
stz ControlPort+5
sty ControlPort+6 ; P2-P3 : Y
stz ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
b0: .byte 32, 1, 0 ; 32,1 : Init Graf
b1: .byte 32, 4, 1, 7 ; 32,4 : Set Pen Colour
b2: .byte 32, 5, 4 ; 32,5 : Move To
.word 50, 60
b3: .byte 32, 11, 4 ; Line To : le point d'arrivée est tracé
.word 60, 60
p1: .byte 0
p2: .byte 0
p3: .byte 0
b4: .byte 32, 1, 0 ; 32,1 : Init Graf
t5: .text "Depart : ", 0
t6: .text ", arrivee : ", 0
t7: .text ", apres : ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Depart : 7, arrivee : 7, apres : 032,12 Set Pattern Trinity
Loads the 8 × 8 pattern used by 32,13.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of the 8 pattern bytes: one byte per row, bit 7 = left pixel |
Outputs: none.
The pattern is aligned on screen coordinates, not on the rectangle: the example fills from x = 96, a multiple of 8, so that the first column gets bit 7. 32,1 restores the solid pattern. The example loads a checkerboard ($AA, $55): set bits in colour 3, clear bits in colour 9. NeoBASIC has no keyword for this call.
Firmware documentation text
Loads the 8x8 fill pattern from the 8 bytes at Parameters:0,1 (one byte per row, bit 7 = left pixel). Init Graf resets it to solid. The pattern is aligned on screen coordinates.
C (llvm-mos)
/* Choisir le motif de remplissage (groupe 32, fonction 12, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static const uint8_t damier[8] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
static void motif(const uint8_t *m) { /* 32,12 Set Pattern : 8 octets, bit 7 = pixel de gauche */
libre();
ControlPort.params[0] = (uint16_t)m & 0xFF;
ControlPort.params[1] = (uint16_t)m >> 8;
qd(12);
}
static void remplir(Rect *r, uint8_t fond) { /* 32,13 Fill Rect : bits à 1 couleur de la plume, à 0 fond */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
ControlPort.params[2] = fond;
qd(13);
}
static Rect r = {96, 100, 104, 102}; /* x 96 à 103 : une rangée du motif, alignée sur l'écran */
int main(void) {
putchar(12);
init_graf();
couleur(3);
motif(damier); /* Set Pattern */
remplir(&r, 9);
uint8_t l[2][8];
for (uint8_t y = 0; y < 2; y++)
for (uint8_t x = 0; x < 8; x++)
l[y][x] = px(96 + x, 100 + y);
init_graf(); /* remet aussi le motif plein */
for (uint8_t y = 0; y < 2; y++) {
printf("y %u :", 100 + y);
for (uint8_t x = 0; x < 8; x++)
printf(" %u", l[y][x]);
printf("\n");
}
return 0;
}y 100 : 3 9 3 9 3 9 3 9
y 101 : 9 3 9 3 9 3 9 3Mad Pascal
// Choisir le motif de remplissage (groupe 32, fonction 12, Trinity).
program qd12;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
const damier: array[0..7] of byte = ($AA, $55, $AA, $55, $AA, $55, $AA, $55);
procedure motif(m: pointer); // 32,12 Set Pattern : 8 octets, bit 7 = pixel de gauche
begin
qd_rect(12, m);
end;
procedure remplir(r: pointer; fond: byte); // 32,13 Fill Rect : bits à 1 couleur de la plume, à 0 fond
begin
NeoWaitMessage;
wordParams[0] := word(r);
NeoMessage.params[2] := fond;
qd(13);
end;
var r: Rect;
l: array[0..15] of byte;
x, y: byte;
begin
write(chr(12));
r.g := 96; r.h := 100; r.d := 104; r.b := 102; // x 96 à 103 : une rangée du motif, alignée sur l'écran
init_graf;
couleur(3);
motif(@damier); // Set Pattern
remplir(@r, 9);
for y := 0 to 1 do
for x := 0 to 7 do l[y * 8 + x] := NeoGetPixel(96 + x, 100 + y);
init_graf; // remet aussi le motif plein
for y := 0 to 1 do begin
write('y ', 100 + y, ' :');
for x := 0 to 7 do write(' ', l[y * 8 + x]);
writeln;
end;
end.y 100 : 3 9 3 9 3 9 3 9
y 101 : 9 3 9 3 9 3 9 3NeoBASIC
10 ' Choisir le motif de remplissage (groupe 32, fonction 12, Trinity)
20 cls : q = alloc(8) : g = 96 : h = 100 : d = 104 : b = 102 : gosub 8000 : ' x 96 a 103 : une rangee du motif, alignee sur l'ecran
30 m = alloc(8) : for i = 0 to 3 : poke m + i * 2, $aa : poke m + i * 2 + 1, $55 : next i : ' damier, bit 7 = pixel de gauche
40 gosub 9400 : c = 3 : gosub 9300
50 a = m : f = 12 : gosub 9000 : ' Set Pattern
60 while peek($ff00) : wend : doke $ff04, q : poke $ff06, 9 : f = 13 : gosub 9110 : ' 32,13 : bits a 0 en couleur 9
70 l0$ = "" : l1$ = "" : for x = 96 to 103 : l0$ = l0$ + " " + str$(point(x, 100)) : l1$ = l1$ + " " + str$(point(x, 101)) : next x
80 gosub 9400 : ' remet aussi le motif plein
90 print "y 100 :";l0$
100 print "y 101 :";l1$
110 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110y 100 : 3 9 3 9 3 9 3 9
y 101 : 9 3 9 3 9 3 9 365C02 assembly (64tass)
; Choisir le motif de remplissage (groupe 32, fonction 12, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda #<b2
ldx #>b2
jsr envoi
lda #<b3
ldx #>b3
jsr envoi
ldx #0
_l4: phx
txa
clc
adc #96
ldy #100
jsr pixel
plx
sta l0,x
inx
cpx #8
bne _l4
ldx #0
_l5: phx
txa
clc
adc #96
ldy #101
jsr pixel
plx
sta l1,x
inx
cpx #8
bne _l5
lda #<b6
ldx #>b6
jsr envoi
lda #<t7
ldx #>t7
jsr ecrire
ldx #0
_a8: lda #' '
jsr WriteCharacter
lda l0,x
jsr decimal
inx
cpx #8
bne _a8
lda #13
jsr WriteCharacter
lda #<t9
ldx #>t9
jsr ecrire
ldx #0
_a10: lda #' '
jsr WriteCharacter
lda l1,x
jsr decimal
inx
cpx #8
bne _a10
lda #13
jsr WriteCharacter
rts
; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : X
stz ControlPort+5
sty ControlPort+6 ; P2-P3 : Y
stz ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
q: .word 96, 100, 104, 102 ; gauche, haut, droite, bas (droite et bas exclus)
motif: .byte $AA, $55, $AA, $55, $AA, $55, $AA, $55 ; damier, bit 7 = pixel de gauche
b0: .byte 32, 1, 0 ; 32,1 : Init Graf
b1: .byte 32, 4, 1, 3 ; 32,4 : Set Pen Colour
b2: .byte 32, 12, 2 ; Set Pattern
.word motif
b3: .byte 32, 13, 3 ; 32,13 : bits à 0 en couleur 9
.word q
.byte 9
l0: .fill 8
l1: .fill 8
b6: .byte 32, 1, 0 ; remet aussi le motif plein
t7: .text "y 100 :", 0
t9: .text "y 101 :", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0y 100 : 3 9 3 9 3 9 3 9
y 101 : 9 3 9 3 9 3 9 332,13 Fill Rect Trinity
Fills a rectangle with the pattern: set bits in the pen colour, clear bits in the given colour.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of the Rect |
P2 | uint8 | colour of clear bits |
Outputs: none.
With the solid starting pattern, 32,13 does the same as 32,8. The example then fills with stripes ($F0: four pixels on, four off). NeoBASIC has no keyword for this call.
Firmware documentation text
Fills the Rect at Parameters:0,1 with the pattern : set bits in the pen colour, clear bits in the colour of Parameter:2. Clipped.
C (llvm-mos)
/* Remplir un rectangle avec le motif (groupe 32, fonction 13, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static const uint8_t damier[8] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
static void motif(const uint8_t *m) { /* 32,12 Set Pattern : 8 octets, bit 7 = pixel de gauche */
libre();
ControlPort.params[0] = (uint16_t)m & 0xFF;
ControlPort.params[1] = (uint16_t)m >> 8;
qd(12);
}
static void remplir(Rect *r, uint8_t fond) { /* 32,13 Fill Rect : bits à 1 couleur de la plume, à 0 fond */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
ControlPort.params[2] = fond;
qd(13);
}
static const uint8_t rayures[8] = {0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0}; /* 4 pixels allumés, 4 éteints */
static Rect r = {96, 100, 104, 101};
int main(void) {
putchar(12);
init_graf();
uint8_t avant[2] = {px(96, 100), px(103, 100)};
couleur(3);
remplir(&r, 9); /* Fill Rect, motif plein au départ */
uint8_t plein[2] = {px(96, 100), px(103, 100)};
motif(rayures);
remplir(&r, 9); /* Fill Rect : 3 pour les bits à 1, 9 pour les bits à 0 */
uint8_t ray[2] = {px(96, 100), px(103, 100)};
init_graf();
printf("Avant : %u %u, motif plein : %u %u, rayures : %u %u\n", avant[0], avant[1], plein[0], plein[1], ray[0], ray[1]);
return 0;
}Avant : 0 0, motif plein : 3 3, rayures : 3 9Mad Pascal
// Remplir un rectangle avec le motif (groupe 32, fonction 13, Trinity).
program qd13;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
const damier: array[0..7] of byte = ($AA, $55, $AA, $55, $AA, $55, $AA, $55);
procedure motif(m: pointer); // 32,12 Set Pattern : 8 octets, bit 7 = pixel de gauche
begin
qd_rect(12, m);
end;
procedure remplir(r: pointer; fond: byte); // 32,13 Fill Rect : bits à 1 couleur de la plume, à 0 fond
begin
NeoWaitMessage;
wordParams[0] := word(r);
NeoMessage.params[2] := fond;
qd(13);
end;
const rayures: array[0..7] of byte = ($F0, $F0, $F0, $F0, $F0, $F0, $F0, $F0); // 4 pixels allumés, 4 éteints
var r: Rect;
a0, a1, p0, p1, r0, r1: byte;
begin
write(chr(12));
r.g := 96; r.h := 100; r.d := 104; r.b := 101;
init_graf;
a0 := NeoGetPixel(96, 100); a1 := NeoGetPixel(103, 100);
couleur(3);
remplir(@r, 9); // Fill Rect, motif plein au départ
p0 := NeoGetPixel(96, 100); p1 := NeoGetPixel(103, 100);
motif(@rayures);
remplir(@r, 9); // Fill Rect : 3 pour les bits à 1, 9 pour les bits à 0
r0 := NeoGetPixel(96, 100); r1 := NeoGetPixel(103, 100);
init_graf;
writeln('Avant : ', a0, ' ', a1, ', motif plein : ', p0, ' ', p1, ', rayures : ', r0, ' ', r1);
end.Avant : 0 0, motif plein : 3 3, rayures : 3 9NeoBASIC
10 ' Remplir un rectangle avec le motif (groupe 32, fonction 13, Trinity)
20 cls : q = alloc(8) : g = 96 : h = 100 : d = 104 : b = 101 : gosub 8000
30 m = alloc(8) : for i = 0 to 7 : poke m + i, $f0 : next i : ' rayures : 4 pixels allumes, 4 eteints
40 gosub 9400 : a0 = point(96, 100) : a1 = point(103, 100)
50 c = 3 : gosub 9300
60 gosub 2000 : p0 = point(96, 100) : p1 = point(103, 100) : ' Fill Rect, motif plein au depart
70 a = m : f = 12 : gosub 9000
80 gosub 2000 : r0 = point(96, 100) : r1 = point(103, 100) : ' 3 pour les bits a 1, 9 pour les bits a 0
90 gosub 9400
100 print "Avant : ";a0;" ";a1;", motif plein : ";p0;" ";p1;", rayures : ";r0;" ";r1
110 end
2000 ' Fill Rect sur q, fond 9
2010 while peek($ff00) : wend : doke $ff04, q : poke $ff06, 9 : f = 13 : gosub 9110
2020 return
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110Avant : 0 0, motif plein : 3 3, rayures : 3 965C02 assembly (64tass)
; Remplir un rectangle avec le motif (groupe 32, fonction 13, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #96
ldy #100
jsr pixel
sta a0
lda #103
ldy #100
jsr pixel
sta a1
lda #<b1
ldx #>b1
jsr envoi
lda #<b2
ldx #>b2
jsr envoi
lda #96
ldy #100
jsr pixel
sta p0
lda #103
ldy #100
jsr pixel
sta p1
lda #<b3
ldx #>b3
jsr envoi
lda #<b4
ldx #>b4
jsr envoi
lda #96
ldy #100
jsr pixel
sta r0
lda #103
ldy #100
jsr pixel
sta r1
lda #<b5
ldx #>b5
jsr envoi
lda #<t6
ldx #>t6
jsr ecrire
lda a0
jsr decimal
lda #<t7
ldx #>t7
jsr ecrire
lda a1
jsr decimal
lda #<t8
ldx #>t8
jsr ecrire
lda p0
jsr decimal
lda #<t9
ldx #>t9
jsr ecrire
lda p1
jsr decimal
lda #<t10
ldx #>t10
jsr ecrire
lda r0
jsr decimal
lda #<t11
ldx #>t11
jsr ecrire
lda r1
jsr decimal
lda #13
jsr WriteCharacter
rts
; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : X
stz ControlPort+5
sty ControlPort+6 ; P2-P3 : Y
stz ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
q: .word 96, 100, 104, 101 ; gauche, haut, droite, bas (droite et bas exclus)
motif: .fill 8, $F0 ; rayures : 4 pixels allumés, 4 éteints
b0: .byte 32, 1, 0 ; 32,1 : Init Graf
a0: .byte 0
a1: .byte 0
b1: .byte 32, 4, 1, 3 ; 32,4 : Set Pen Colour
b2: .byte 32, 13, 3 ; Fill Rect, motif plein au départ, fond 9
.word q
.byte 9
p0: .byte 0
p1: .byte 0
b3: .byte 32, 12, 2 ; 32,12
.word motif
b4: .byte 32, 13, 3 ; 3 pour les bits à 1, 9 pour les bits à 0
.word q
.byte 9
r0: .byte 0
r1: .byte 0
b5: .byte 32, 1, 0 ; 32,1 : Init Graf
t6: .text "Avant : ", 0
t7: .text " ", 0
t8: .text ", motif plein : ", 0
t9: .text " ", 0
t10: .text ", rayures : ", 0
t11: .text " ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Avant : 0 0, motif plein : 3 3, rayures : 3 932,14 Copy Bits Trinity
Draws a source area (described as for 12,3) on the draw page, clipped by the rectangle of 32,2.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | action: 0 copy, 1 masked, 2 solid colour |
P1-P2 | addr | address of the 12-byte source descriptor |
P3-P4 | int16 | X (signed) |
P5-P6 | int16 | Y (signed) |
Outputs: none.
All source formats of 12,3 are accepted. The example draws 8 pixels of 4 bits (1 to 8) at (100, 120) under a clip that stops before x = 104: only the first four show. As for 12,4, a clipped left edge is rounded up to a whole source byte. Outside mode 0, the copy is done pixel by pixel. NeoBASIC has no keyword for this call.
Firmware documentation text
Blits the source area described at Parameters:1,2 (the 12 byte structure of Function 12,3, any source format) at Parameters:3,4 (X) and Parameters:5,6 (Y) of the draw page, with the blit action of Parameter:0 (0 copy, 1 masked, 2 solid), clipped to the clip rectangle. As Function 12,4, the left clip is rounded up to a whole source byte. Outside mode 0 the copy is done pixel by pixel (source values are reduced to their bit 0 in monochrome).
C (llvm-mos)
/* Copier une image dans la zone de dessin, découpée (groupe 32, fonction 14, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static uint8_t pixels[4] = {0x12, 0x34, 0x56, 0x78}; /* 8 pixels de 4 bits : 1 à 8 */
static uint8_t source[12]; /* descripteur de zone de 12,3 */
static Rect zone = {0, 0, 104, 240}; /* découpe : rien au-delà de x = 103 */
int main(void) {
putchar(12);
init_graf();
source[0] = (uint16_t)pixels & 0xFF; /* adresse en RAM du 6502 (page $00) */
source[1] = (uint16_t)pixels >> 8;
source[6] = 1; /* format 1 : paires de 4 bits */
source[9] = 1; /* hauteur */
source[10] = 8; /* largeur */
qd_rect(2, &zone); /* 32,2 */
libre();
ControlPort.params[0] = 0; /* P0 : action 0, copie */
ControlPort.params[1] = (uint16_t)source & 0xFF; /* P1-P2 : zone source */
ControlPort.params[2] = (uint16_t)source >> 8;
ControlPort.params[3] = 100; /* P3-P4 : X */
ControlPort.params[4] = 0;
ControlPort.params[5] = 120; /* P5-P6 : Y */
ControlPort.params[6] = 0;
uint8_t e = qd(14); /* Copy Bits */
uint8_t l[8];
for (uint8_t x = 0; x < 8; x++)
l[x] = px(100 + x, 120);
init_graf();
printf("Erreur %u ; x 100 a 107 :", e);
for (uint8_t x = 0; x < 8; x++)
printf(" %u", l[x]);
printf("\n");
return 0;
}Erreur 0 ; x 100 a 107 : 1 2 3 4 0 0 0 0Mad Pascal
// Copier une image dans la zone de dessin, découpée (groupe 32, fonction 14, Trinity).
program qd14;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
const pixels: array[0..3] of byte = ($12, $34, $56, $78); // 8 pixels de 4 bits : 1 à 8
var source: array[0..11] of byte; // descripteur de zone de 12,3
zone: Rect;
l: array[0..7] of byte;
x, e: byte;
begin
write(chr(12));
init_graf;
fillchar(@source, 12, 0);
source[0] := lo(word(@pixels)); // adresse en RAM du 6502 (page $00)
source[1] := hi(word(@pixels));
source[6] := 1; // format 1 : paires de 4 bits
source[9] := 1; // hauteur
source[10] := 8; // largeur
zone.g := 0; zone.h := 0; zone.d := 104; zone.b := 240; // découpe : rien au-delà de x = 103
qd_rect(2, @zone);
NeoWaitMessage;
NeoMessage.params[0] := 0; // P0 : action 0, copie
wordxParams[0] := word(@source); // P1-P2 : zone source
wordxParams[1] := 100; // P3-P4 : X
wordxParams[2] := 120; // P5-P6 : Y
e := qd(14); // Copy Bits
for x := 0 to 7 do l[x] := NeoGetPixel(100 + x, 120);
init_graf;
write('Erreur ', e, ' ; x 100 a 107 :');
for x := 0 to 7 do write(' ', l[x]);
writeln;
end.Erreur 0 ; x 100 a 107 : 1 2 3 4 0 0 0 0NeoBASIC
10 ' Copier une image dans la zone de dessin, decoupee (groupe 32, fonction 14, Trinity)
20 cls : gosub 9400
30 pp = alloc(4) : poke pp, $12 : poke pp + 1, $34 : poke pp + 2, $56 : poke pp + 3, $78 : ' 8 pixels de 4 bits : 1 a 8
40 s = alloc(12) : for i = 0 to 11 : poke s + i, 0 : next i
50 doke s, pp : poke s + 6, 1 : poke s + 9, 1 : poke s + 10, 8 : ' descripteur de 12,3 : format 1, hauteur 1, largeur 8
60 q = alloc(8) : g = 0 : h = 0 : d = 104 : b = 240 : gosub 8000 : a = q : f = 2 : gosub 9000 : ' decoupe : rien au-dela de x = 103
70 while peek($ff00) : wend
80 poke $ff04, 0 : doke $ff05, s : doke $ff07, 100 : doke $ff09, 120 : f = 14 : gosub 9110 : ' Copy Bits : action 0, en (100, 120)
90 l$ = "" : for x = 100 to 107 : l$ = l$ + " " + str$(point(x, 120)) : next x
100 gosub 9400
110 print "Erreur ";e;" ; x 100 a 107 :";l$
120 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110Erreur 0 ; x 100 a 107 : 1 2 3 4 0 0 0 065C02 assembly (64tass)
; Copier une image dans la zone de dessin, découpée (groupe 32, fonction 14, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda #<b2
ldx #>b2
jsr envoi
lda ControlPort+2
sta e
ldx #0
_l3: phx
txa
clc
adc #100
ldy #120
jsr pixel
plx
sta l,x
inx
cpx #8
bne _l3
lda #<b4
ldx #>b4
jsr envoi
lda #<t5
ldx #>t5
jsr ecrire
lda e
jsr decimal
lda #<t6
ldx #>t6
jsr ecrire
ldx #0
_a7: lda #' '
jsr WriteCharacter
lda l,x
jsr decimal
inx
cpx #8
bne _a7
lda #13
jsr WriteCharacter
rts
; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : X
stz ControlPort+5
sty ControlPort+6 ; P2-P3 : Y
stz ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
q: .word 0, 0, 104, 240 ; gauche, haut, droite, bas (droite et bas exclus)
pixels: .byte $12, $34, $56, $78 ; 8 pixels de 4 bits : 1 à 8
source: .word pixels ; descripteur de 12,3 : adresse en RAM du 6502...
.byte 0, 0 ; ... page $00, octet de bourrage
.word 0 ; pas
.byte 1, 0, 0, 1 ; format 1 (paires de 4 bits), transparent, uni, hauteur 1
.word 8 ; largeur
b0: .byte 32, 1, 0 ; 32,1 : Init Graf
b1: .byte 32, 2, 2 ; découpe : rien au-delà de x = 103
.word q
b2: .byte 32, 14, 7, 0 ; Copy Bits : action 0, en (100, 120)
.word source, 100, 120
e: .byte 0
l: .fill 8
b4: .byte 32, 1, 0 ; 32,1 : Init Graf
t5: .text "Erreur ", 0
t6: .text " ; x 100 a 107 :", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Erreur 0 ; x 100 a 107 : 1 2 3 4 0 0 0 032,15 Set Font Trinity
Selects the proportional font used by 32,16 and 32,17.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | page: $00 6502 RAM, $90 graphics memory |
P1-P2 | addr | font address (0 in page 0: built-in 6 × 8 font) |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | 1 if the header or the size is wrong |
NF1 format: "NF", version 1, height, first character, character count, spacing, bytes per row (1 or 2), then for each character its width and one line per row, bit 7 = left pixel. The font is read in place at each call: it must stay in memory. The example builds a font with a single character, "A", drawn as an 8 × 8 frame, writes it with 32,16, then tries a wrong header before going back to the built-in font. NeoBASIC has no keyword for this call.
Firmware documentation text
Selects the proportional font at page Parameter:0, address Parameters:1,2 (pages of Function 12,2 : $00 6502 RAM, $90 graphics RAM ; load a font file there with Function 3,2 or 12,1). Page 0 address 0 restores the built in 6x8 font. The font is read in place at each call, without copy. NF1 format (made by tools/mkfont.py of the fork archive) : "NF", version 1, height, first character, character count, spacing, bytes per row (1 or 2), then one glyph per character of width byte plus height rows, bit 7 = left pixel. Error 1 if the header or the size is invalid.
C (llvm-mos)
/* Choisir une police proportionnelle (groupe 32, fonction 15, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
/* Une police NF1 d'un seul caractère, « A » : en-tête puis largeur et 8 rangées (bit 7 = pixel de gauche). */
static const uint8_t police[] = {'N', 'F', 1, 8, 'A', 1, 1, 1, /* NF, version 1, hauteur 8, premier « A », 1 caractère, espacement 1, 1 octet par rangée */
8, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF}; /* largeur 8 : un cadre */
static uint8_t choisir_police(uint8_t page, uint16_t adresse) { /* 32,15 Set Font */
libre();
ControlPort.params[0] = page; /* P0 : page ($00 RAM du 6502, $90 mémoire graphique) */
ControlPort.params[1] = adresse & 0xFF; /* P1-P2 : adresse */
ControlPort.params[2] = adresse >> 8;
return qd(15);
}
static void ecrire_qd(const uint8_t *s) { /* 32,16 Draw String : chaîne précédée de sa longueur */
libre();
ControlPort.params[0] = (uint16_t)s & 0xFF;
ControlPort.params[1] = (uint16_t)s >> 8;
qd(16);
}
static const uint8_t faux[] = {'X', 'F', 1, 8, 'A', 1, 1, 1};
static const uint8_t texte[] = "\x01" "A";
int main(void) {
putchar(12);
init_graf();
uint8_t e = choisir_police(0x00, (uint16_t)police); /* Set Font */
couleur(6);
qd_xy(5, 100, 100);
ecrire_qd(texte); /* 32,16 : le « A » de la police, un cadre 8x8 */
uint8_t coin = px(100, 100), milieu = px(104, 104);
uint8_t f = choisir_police(0x00, (uint16_t)faux); /* en-tête faux : refusé */
choisir_police(0x00, 0); /* page 0, adresse 0 : police intégrée */
init_graf();
printf("Police : erreur %u ; coin %u, milieu %u\n", e, coin, milieu);
printf("En-tete faux : erreur %u\n", f);
return 0;
}Police : erreur 0 ; coin 6, milieu 0
En-tete faux : erreur 1Mad Pascal
// Choisir une police proportionnelle (groupe 32, fonction 15, Trinity).
program qd15;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
// Une police NF1 d'un seul caractère, « A » : en-tête puis largeur et 8 rangées (bit 7 = pixel de gauche).
const police: array[0..16] of byte = (ord('N'), ord('F'), 1, 8, ord('A'), 1, 1, 1, // NF, version 1, hauteur 8, premier « A », 1 caractère, espacement 1, 1 octet par rangée
8, $FF, $81, $81, $81, $81, $81, $81, $FF); // largeur 8 : un cadre
function choisir_police(page: byte; adresse: word): byte; // 32,15 Set Font
begin
NeoWaitMessage;
NeoMessage.params[0] := page; // P0 : page ($00 RAM du 6502, $90 mémoire graphique)
wordxParams[0] := adresse; // P1-P2 : adresse
result := qd(15);
end;
procedure ecrire_qd(s: pointer); // 32,16 Draw String : chaîne précédée de sa longueur
begin
qd_rect(16, s);
end;
const faux: array[0..7] of byte = (ord('X'), ord('F'), 1, 8, ord('A'), 1, 1, 1);
texte: array[0..1] of byte = (1, ord('A')); // chaîne précédée de sa longueur
var e, f, coin, milieu: byte;
begin
write(chr(12));
init_graf;
e := choisir_police($00, word(@police)); // Set Font
couleur(6);
qd_xy(5, 100, 100);
ecrire_qd(@texte); // 32,16 : le « A » de la police, un cadre 8x8
coin := NeoGetPixel(100, 100);
milieu := NeoGetPixel(104, 104);
f := choisir_police($00, word(@faux)); // en-tête faux : refusé
choisir_police($00, 0); // page 0, adresse 0 : police intégrée
init_graf;
writeln('Police : erreur ', e, ' ; coin ', coin, ', milieu ', milieu);
writeln('En-tete faux : erreur ', f);
end.Police : erreur 0 ; coin 6, milieu 0
En-tete faux : erreur 1NeoBASIC
10 ' Choisir une police proportionnelle (groupe 32, fonction 15, Trinity)
20 cls : gosub 9400
30 po = alloc(17) : for i = 0 to 16 : read v : poke po + i, v : next i
40 data 78, 70, 1, 8, 65, 1, 1, 1 : ' NF, version 1, hauteur 8, premier A, 1 caractere, espacement 1, 1 octet par rangee
50 data 8, 255, 129, 129, 129, 129, 129, 129, 255 : ' largeur 8 : un cadre
60 fx = alloc(8) : for i = 0 to 7 : poke fx + i, peek(po + i) : next i : poke fx, asc("X") : ' en-tete faux
70 t = alloc(2) : poke t, 1 : poke t + 1, asc("A")
80 pg = 0 : ad = po : gosub 2000 : e1 = e : ' Set Font
90 c = 6 : gosub 9300 : x = 100 : y = 100 : f = 5 : gosub 9200
100 a = t : f = 16 : gosub 9000 : ' 32,16 : le A de la police, un cadre 8x8
110 co = point(100, 100) : mi = point(104, 104)
120 ad = fx : gosub 2000 : e2 = e : ' en-tete faux : refuse
130 ad = 0 : gosub 2000 : ' page 0, adresse 0 : police integree
140 gosub 9400
150 print "Police : erreur ";e1;" ; coin ";co;", milieu ";mi
160 print "En-tete faux : erreur ";e2
170 end
2000 ' Set Font : page pg, adresse ad
2010 while peek($ff00) : wend : poke $ff04, pg : doke $ff05, ad : f = 15 : gosub 9110
2020 return
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110Police : erreur 0 ; coin 6, milieu 0
En-tete faux : erreur 165C02 assembly (64tass)
; Choisir une police proportionnelle (groupe 32, fonction 15, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda ControlPort+2
sta e1
lda #<b2
ldx #>b2
jsr envoi
lda #<b3
ldx #>b3
jsr envoi
lda #<b4
ldx #>b4
jsr envoi
lda #100
ldy #100
jsr pixel
sta co
lda #104
ldy #104
jsr pixel
sta mi
lda #<b5
ldx #>b5
jsr envoi
lda ControlPort+2
sta e2
lda #<b6
ldx #>b6
jsr envoi
lda #<b7
ldx #>b7
jsr envoi
lda #<t8
ldx #>t8
jsr ecrire
lda e1
jsr decimal
lda #<t9
ldx #>t9
jsr ecrire
lda co
jsr decimal
lda #<t10
ldx #>t10
jsr ecrire
lda mi
jsr decimal
lda #13
jsr WriteCharacter
lda #<t11
ldx #>t11
jsr ecrire
lda e2
jsr decimal
lda #13
jsr WriteCharacter
rts
; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : X
stz ControlPort+5
sty ControlPort+6 ; P2-P3 : Y
stz ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
police: .text "NF" ; en-tête
.byte 1, 8, 'A', 1 ; version 1, hauteur 8, premier A, 1 caractère
.byte 1, 1 ; espacement 1, 1 octet par rangée
.byte 8, $FF, $81, $81, $81, $81, $81, $81, $FF ; largeur 8 : un cadre
faux: .text "XF" ; en-tête faux
.byte 1, 8, 'A', 1, 1, 1
texte: .byte 1, 'A'
b0: .byte 32, 1, 0 ; 32,1 : Init Graf
b1: .byte 32, 15, 3, 0 ; Set Font : page 0, adresse
.word police
e1: .byte 0
b2: .byte 32, 4, 1, 6 ; 32,4 : Set Pen Colour
b3: .byte 32, 5, 4 ; 32,5 : Move To
.word 100, 100
b4: .byte 32, 16, 2 ; 32,16 : le A de la police, un cadre 8x8
.word texte
co: .byte 0
mi: .byte 0
b5: .byte 32, 15, 3, 0 ; en-tête faux : refusé
.word faux
e2: .byte 0
b6: .byte 32, 15, 3, 0 ; page 0, adresse 0 : police intégrée
.word 0
b7: .byte 32, 1, 0 ; 32,1 : Init Graf
t8: .text "Police : erreur ", 0
t9: .text " ; coin ", 0
t10: .text ", milieu ", 0
t11: .text "En-tete faux : erreur ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Police : erreur 0 ; coin 6, milieu 0
En-tete faux : erreur 132,16 Draw String Trinity
Writes a string with the current font, top left corner at the pen, in the pen colour; the pen moves on.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of the string, preceded by its length |
Outputs: none.
The unset pixels of characters leave the background alone (transparency). The pen moves on by the width of each character plus the font spacing: "AB" in the built-in 6 × 8 font takes it from x = 100 to 112. Characters missing from the font are skipped without moving. NeoBASIC has no keyword for this call.
Firmware documentation text
Draws the length-prefixed string at Parameters:0,1 with the current font, top left at the pen, set pixels in the pen colour, other pixels untouched (transparent), clipped ; the pen advances by the width of each glyph plus the font spacing. Characters absent from the font are skipped without advance.
C (llvm-mos)
/* Écrire un texte à la plume (groupe 32, fonction 16, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static int16_t plume_x, plume_y;
static uint8_t plume_c;
static void get_pen(void) { /* 32,6 Get Pen */
libre();
qd(6);
plume_x = ControlPort.params[0] | ControlPort.params[1] << 8;
plume_y = ControlPort.params[2] | ControlPort.params[3] << 8;
plume_c = ControlPort.params[4];
}
/* Une police NF1 d'un seul caractère, « A » : en-tête puis largeur et 8 rangées (bit 7 = pixel de gauche). */
static const uint8_t police[] = {'N', 'F', 1, 8, 'A', 1, 1, 1, /* NF, version 1, hauteur 8, premier « A », 1 caractère, espacement 1, 1 octet par rangée */
8, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF}; /* largeur 8 : un cadre */
static uint8_t choisir_police(uint8_t page, uint16_t adresse) { /* 32,15 Set Font */
libre();
ControlPort.params[0] = page; /* P0 : page ($00 RAM du 6502, $90 mémoire graphique) */
ControlPort.params[1] = adresse & 0xFF; /* P1-P2 : adresse */
ControlPort.params[2] = adresse >> 8;
return qd(15);
}
static void ecrire_qd(const uint8_t *s) { /* 32,16 Draw String : chaîne précédée de sa longueur */
libre();
ControlPort.params[0] = (uint16_t)s & 0xFF;
ControlPort.params[1] = (uint16_t)s >> 8;
qd(16);
}
static const uint8_t texte[] = "\x02" "AB";
int main(void) {
putchar(12);
init_graf(); /* police intégrée 6x8 */
couleur(6);
qd_xy(5, 100, 100);
ecrire_qd(texte); /* Draw String : en haut à gauche à la plume */
get_pen();
uint8_t n = 0;
for (uint8_t y = 100; y < 108; y++)
for (uint8_t x = 100; x < 112; x++)
n += px(x, y) == 6;
init_graf();
printf("Plume apres AB : %d, %d ; pixels allumes : %u\n", plume_x, plume_y, n);
return 0;
}Plume apres AB : 112, 100 ; pixels allumes : 35Mad Pascal
// Écrire un texte à la plume (groupe 32, fonction 16, Trinity).
program qd16;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
var plume_x, plume_y: smallint;
plume_c: byte;
procedure get_pen; // 32,6 Get Pen
begin
NeoWaitMessage;
qd(6);
plume_x := smallint(wordParams[0]);
plume_y := smallint(wordParams[1]);
plume_c := NeoMessage.params[4];
end;
// Une police NF1 d'un seul caractère, « A » : en-tête puis largeur et 8 rangées (bit 7 = pixel de gauche).
const police: array[0..16] of byte = (ord('N'), ord('F'), 1, 8, ord('A'), 1, 1, 1, // NF, version 1, hauteur 8, premier « A », 1 caractère, espacement 1, 1 octet par rangée
8, $FF, $81, $81, $81, $81, $81, $81, $FF); // largeur 8 : un cadre
function choisir_police(page: byte; adresse: word): byte; // 32,15 Set Font
begin
NeoWaitMessage;
NeoMessage.params[0] := page; // P0 : page ($00 RAM du 6502, $90 mémoire graphique)
wordxParams[0] := adresse; // P1-P2 : adresse
result := qd(15);
end;
procedure ecrire_qd(s: pointer); // 32,16 Draw String : chaîne précédée de sa longueur
begin
qd_rect(16, s);
end;
const texte: string[2] = 'AB';
var n, x, y: byte;
begin
write(chr(12));
init_graf; // police intégrée 6x8
couleur(6);
qd_xy(5, 100, 100);
ecrire_qd(@texte); // Draw String : en haut à gauche à la plume
get_pen;
n := 0;
for y := 100 to 107 do
for x := 100 to 111 do
if NeoGetPixel(x, y) = 6 then inc(n);
init_graf;
writeln('Plume apres AB : ', plume_x, ', ', plume_y, ' ; pixels allumes : ', n);
end.Plume apres AB : 112, 100 ; pixels allumes : 35NeoBASIC
10 ' Ecrire un texte a la plume (groupe 32, fonction 16, Trinity)
20 cls : gosub 9400 : ' police integree 6x8
30 t = alloc(3) : poke t, 2 : poke t + 1, asc("A") : poke t + 2, asc("B")
40 c = 6 : gosub 9300 : x = 100 : y = 100 : f = 5 : gosub 9200
50 a = t : f = 16 : gosub 9000 : ' Draw String : en haut a gauche a la plume
60 gosub 9500
70 n = 0 : for y = 100 to 107 : for x = 100 to 111 : if point(x, y) = 6 then n = n + 1
80 next x : next y
90 gosub 9400
100 print "Plume apres AB : ";px;", ";py;" ; pixels allumes : ";n
110 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
9500 ' 32,6 Get Pen : px, py, pc
9510 while peek($ff00) : wend : f = 6 : gosub 9110
9520 px = deek($ff04) : py = deek($ff06) : pc = peek($ff08)
9530 if px > 32767 then px = px - 65536
9540 if py > 32767 then py = py - 65536
9550 returnPlume apres AB : 112, 100 ; pixels allumes : 3565C02 assembly (64tass)
; Écrire un texte à la plume (groupe 32, fonction 16, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #12 ; écran effacé : on relit des pixels
jsr WriteCharacter
lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda #<b2
ldx #>b2
jsr envoi
lda #<b3
ldx #>b3
jsr envoi
lda #<b5
ldx #>b5
jsr envoi
ldx #4
_c4: lda ControlPort+4,x
sta pen,x
dex
bpl _c4
stz n ; pixels de couleur 6 dans x 100 à 111, y 100 à 107
lda #100
sta yy
_y: lda #100
sta xx
_x: lda xx
ldy yy
jsr pixel
cmp #6
bne _nx
inc n
_nx: inc xx
lda xx
cmp #112
bne _x
inc yy
lda yy
cmp #108
bne _y
lda #<b6
ldx #>b6
jsr envoi
lda #<t7
ldx #>t7
jsr ecrire
lda pen
ldx pen+1
jsr dec16
lda #<t8
ldx #>t8
jsr ecrire
lda pen+2
ldx pen+2+1
jsr dec16
lda #<t9
ldx #>t9
jsr ecrire
lda n
jsr decimal
lda #13
jsr WriteCharacter
rts
; Couleur du fond (5,33) en (A, Y), X et Y inférieurs à 256, rendue dans A.
pixel: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0-P1 : X
stz ControlPort+5
sty ControlPort+6 ; P2-P3 : Y
stz ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
texte: .byte 2
.text "AB"
n: .byte 0
xx: .byte 0
yy: .byte 0
b0: .byte 32, 1, 0 ; police intégrée 6x8
b1: .byte 32, 4, 1, 6 ; 32,4 : Set Pen Colour
b2: .byte 32, 5, 4 ; 32,5 : Move To
.word 100, 100
b3: .byte 32, 16, 2 ; Draw String : en haut à gauche à la plume
.word texte
b5: .byte 32, 6, 0 ; 32,6 : Get Pen
pen: .fill 5 ; x, y (16 bits), couleur
b6: .byte 32, 1, 0 ; 32,1 : Init Graf
t7: .text "Plume apres AB : ", 0
t8: .text ", ", 0
t9: .text " ; pixels allumes : ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Plume apres AB : 112, 100 ; pixels allumes : 3532,17 Text Width Trinity
Returns the width in pixels a string would take when written by 32,16, without drawing anything.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of the string, preceded by its length |
| Bytes | Type | Meaning |
|---|---|---|
P2-P3 | uint16 | width in pixels |
In the built-in font, each character counts 6 pixels: "Neo6502" takes 42. NeoBASIC has no keyword for this call.
Firmware documentation text
Returns in Parameters:2,3 the width in pixels the string at Parameters:0,1 would take with Draw String.
C (llvm-mos)
/* Mesurer un texte avant de l'écrire (groupe 32, fonction 17, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static const uint8_t texte[] = "\x07" "Neo6502";
static uint16_t largeur(const uint8_t *s) { /* Text Width */
libre();
ControlPort.params[0] = (uint16_t)s & 0xFF;
ControlPort.params[1] = (uint16_t)s >> 8;
qd(17);
return ControlPort.params[2] | ControlPort.params[3] << 8;
}
int main(void) {
init_graf(); /* police intégrée 6x8 */
printf("Neo6502 : %u pixels\n", largeur(texte));
return 0;
}Neo6502 : 42 pixelsMad Pascal
// Mesurer un texte avant de l'écrire (groupe 32, fonction 17, Trinity).
program qd17;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
const texte: string[7] = 'Neo6502';
var l: word;
begin
init_graf; // police intégrée 6x8
qd_rect(17, @texte); // Text Width
l := wordParams[1]; // P2-P3 : largeur en pixels
writeln('Neo6502 : ', l, ' pixels');
end.Neo6502 : 42 pixelsNeoBASIC
10 ' Mesurer un texte avant de l'ecrire (groupe 32, fonction 17, Trinity)
20 gosub 9400 : ' police integree 6x8
30 t = alloc(8) : t$ = "Neo6502" : poke t, len(t$) : for i = 1 to len(t$) : poke t + i, asc(mid$(t$, i, 1)) : next i
40 a = t : f = 17 : gosub 9000 : l = deek($ff06) : ' Text Width : largeur en P2-P3
50 print "Neo6502 : ";l;" pixels"
60 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110Neo6502 : 42 pixels65C02 assembly (64tass)
; Mesurer un texte avant de l'écrire (groupe 32, fonction 17, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda ControlPort+6 ; P2-P3 : largeur en pixels
sta l
lda ControlPort+7
sta l+1
lda #<t2
ldx #>t2
jsr ecrire
lda l
ldx l+1
jsr dec16
lda #<t3
ldx #>t3
jsr ecrire
lda #13
jsr WriteCharacter
rts
texte: .byte 7
.text "Neo6502"
b0: .byte 32, 1, 0 ; police intégrée 6x8
b1: .byte 32, 17, 2 ; Text Width : largeur en P2-P3
.word texte
l: .word 0
t2: .text "Neo6502 : ", 0
t3: .text " pixels", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Neo6502 : 42 pixels32,18 Get Font Info Trinity
Returns the height, the first character and the character count of the current font.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | height in pixels |
P1 | uint8 | first character |
P2 | uint8 | character count |
The built-in font is 8 pixels high and covers the 96 characters from 32 (space) to 127. NeoBASIC has no keyword for this call.
Firmware documentation text
Returns the height of the current font in Parameter:0, its first character in Parameter:1 and its character count in Parameter:2.
C (llvm-mos)
/* Lire la hauteur et les caractères de la police (groupe 32, fonction 18, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
int main(void) {
init_graf(); /* police intégrée */
libre();
qd(18); /* Get Font Info */
printf("Hauteur %u, premier caractere %u, %u caracteres\n",
ControlPort.params[0], ControlPort.params[1], ControlPort.params[2]);
return 0;
}Hauteur 8, premier caractere 32, 96 caracteresMad Pascal
// Lire la hauteur et les caractères de la police (groupe 32, fonction 18, Trinity).
program qd18;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
var h, p, n: byte;
begin
init_graf; // police intégrée
NeoWaitMessage;
qd(18); // Get Font Info
h := NeoMessage.params[0];
p := NeoMessage.params[1];
n := NeoMessage.params[2];
writeln('Hauteur ', h, ', premier caractere ', p, ', ', n, ' caracteres');
end.Hauteur 8, premier caractere 32, 96 caracteresNeoBASIC
10 ' Lire la hauteur et les caracteres de la police (groupe 32, fonction 18, Trinity)
20 gosub 9400 : ' police integree
30 while peek($ff00) : wend : f = 18 : gosub 9110 : ' Get Font Info
40 h = peek($ff04) : p = peek($ff05) : n = peek($ff06)
50 print "Hauteur ";h;", premier caractere ";p;", ";n;" caracteres"
60 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110Hauteur 8, premier caractere 32, 96 caracteres65C02 assembly (64tass)
; Lire la hauteur et les caractères de la police (groupe 32, fonction 18, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda ControlPort+4 ; hauteur
sta h
lda ControlPort+5 ; premier caractère
sta pr
lda ControlPort+6 ; nombre de caractères
sta nb
lda #<t2
ldx #>t2
jsr ecrire
lda h
jsr decimal
lda #<t3
ldx #>t3
jsr ecrire
lda pr
jsr decimal
lda #<t4
ldx #>t4
jsr ecrire
lda nb
jsr decimal
lda #<t5
ldx #>t5
jsr ecrire
lda #13
jsr WriteCharacter
rts
b0: .byte 32, 1, 0 ; police intégrée
b1: .byte 32, 18, 0 ; Get Font Info
h: .byte 0
pr: .byte 0
nb: .byte 0
t2: .text "Hauteur ", 0
t3: .text ", premier caractere ", 0
t4: .text ", ", 0
t5: .text " caracteres", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Hauteur 8, premier caractere 32, 96 caracteres32,19 Toolbox Reset Trinity
Puts the whole Trinity toolbox back in its start-up state: no window, menu, control or dialog left, QuickDraw as after 32,1.
Inputs: none.
Outputs: none.
Nothing is drawn or erased. The toolbox keeps its state from one program to the next: according to the Trinity documentation, NeoDOS is to call this function when a program returns to it, and a program may also call it first thing. Unlike 32,1, it is not meant to be called while the program has windows open. The example changes the pen and the clip, then reads them back after the call. NeoBASIC has no keyword for this call.
Firmware documentation text
Puts the whole toolbox back in its start up state (Trinity T-88) : no window, no menu (and the menu bar back to the full width, Function 35,9), no control, no dialog, event manager off, no resource file, QuickDraw as after 32,1. Nothing is drawn or erased. The toolbox otherwise keeps its state from one program to the next : NeoDOS is to call this when a program returns to it (T-88, asked of NeoDOS), so the next program does not inherit its menus or windows. A program may call it first thing as well. Unlike 32,1, which a program may call again while its windows exist.
C (llvm-mos)
/* Remettre toute la boîte à outils dans son état de départ (groupe 32, fonction 19, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
/* QuickDraw : une structure Rect = gauche, haut, droite, bas (16 bits signés ; droite et bas exclus). */
typedef struct { int16_t g, h, d, b; } Rect;
static uint8_t qd(uint8_t f) { /* appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur */
api(32, f);
return ControlPort.error;
}
static uint8_t qd_rect(uint8_t f, Rect *r) { /* appel 32,f sur un Rect : P0-P1 = adresse du Rect */
libre();
ControlPort.params[0] = (uint16_t)r & 0xFF;
ControlPort.params[1] = (uint16_t)r >> 8;
return qd(f);
}
static void qd_xy(uint8_t f, int16_t x, int16_t y) { /* 32,5 Move To ou 32,11 Line To */
libre();
ControlPort.params[0] = x & 0xFF;
ControlPort.params[1] = x >> 8;
ControlPort.params[2] = y & 0xFF;
ControlPort.params[3] = y >> 8;
qd(f);
}
static void couleur(uint8_t c) { /* 32,4 Set Pen Colour */
libre();
ControlPort.params[0] = c;
qd(4);
}
static void init_graf(void) { /* 32,1 Init Graf */
libre();
qd(1);
}
static uint8_t px(uint16_t x, uint16_t y) { /* 5,33 : couleur du pixel */
return neo_graphics_read_pixel(x, y);
}
static int16_t plume_x, plume_y;
static uint8_t plume_c;
static void get_pen(void) { /* 32,6 Get Pen */
libre();
qd(6);
plume_x = ControlPort.params[0] | ControlPort.params[1] << 8;
plume_y = ControlPort.params[2] | ControlPort.params[3] << 8;
plume_c = ControlPort.params[4];
}
static Rect clip;
static void get_clip(void) { /* 32,3 Get Clip : écrit le rectangle de découpe dans clip */
qd_rect(3, &clip);
}
static Rect zone = {10, 10, 50, 50};
int main(void) {
couleur(9); /* un état quelconque */
qd_xy(5, 30, 30);
qd_rect(2, &zone);
libre();
qd(19); /* Toolbox Reset */
get_pen();
get_clip();
printf("Plume : %d, %d, couleur %u ; decoupe : %d, %d, %d, %d\n",
plume_x, plume_y, plume_c, clip.g, clip.h, clip.d, clip.b);
return 0;
}Plume : 0, 0, couleur 15 ; decoupe : 0, 0, 320, 240Mad Pascal
// Remettre toute la boîte à outils dans son état de départ (groupe 32, fonction 19, Trinity).
program qd19;
uses crt, neo6502;
type Rect = record g, h, d, b: smallint; end; // gauche, haut, droite, bas (16 bits signés ; droite et bas exclus)
function qd(f: byte): byte; // appel 32,f (paramètres déjà posés) ; rend l'indicateur d'erreur
begin
NeoSendMessage(32, f);
NeoWaitMessage;
result := NeoMessage.error;
end;
function qd_rect(f: byte; r: pointer): byte; // appel 32,f sur un Rect : P0-P1 = adresse du Rect
begin
NeoWaitMessage;
wordParams[0] := word(r);
result := qd(f);
end;
procedure qd_xy(f: byte; x, y: smallint); // 32,5 Move To ou 32,11 Line To
begin
NeoWaitMessage;
wordParams[0] := word(x);
wordParams[1] := word(y);
qd(f);
end;
procedure couleur(c: byte); // 32,4 Set Pen Colour
begin
NeoWaitMessage;
NeoMessage.params[0] := c;
qd(4);
end;
procedure init_graf; // 32,1 Init Graf
begin
NeoWaitMessage;
qd(1);
end;
var plume_x, plume_y: smallint;
plume_c: byte;
procedure get_pen; // 32,6 Get Pen
begin
NeoWaitMessage;
qd(6);
plume_x := smallint(wordParams[0]);
plume_y := smallint(wordParams[1]);
plume_c := NeoMessage.params[4];
end;
var clip: Rect;
procedure get_clip; // 32,3 Get Clip : écrit le rectangle de découpe dans clip
begin
qd_rect(3, @clip);
end;
var zone: Rect;
begin
zone.g := 10; zone.h := 10; zone.d := 50; zone.b := 50;
couleur(9); // un état quelconque
qd_xy(5, 30, 30);
qd_rect(2, @zone);
NeoWaitMessage;
qd(19); // Toolbox Reset
get_pen;
get_clip;
writeln('Plume : ', plume_x, ', ', plume_y, ', couleur ', plume_c, ' ; decoupe : ', clip.g, ', ', clip.h, ', ', clip.d, ', ', clip.b);
end.Plume : 0, 0, couleur 15 ; decoupe : 0, 0, 320, 240NeoBASIC
10 ' Remettre toute la boite a outils dans son etat de depart (groupe 32, fonction 19, Trinity)
20 k = alloc(8) : q = alloc(8) : g = 10 : h = 10 : d = 50 : b = 50 : gosub 8000
30 c = 9 : gosub 9300 : x = 30 : y = 30 : f = 5 : gosub 9200 : a = q : f = 2 : gosub 9000 : ' un etat quelconque
40 while peek($ff00) : wend : f = 19 : gosub 9110 : ' Toolbox Reset
50 gosub 9500 : gosub 9600
60 print "Plume : ";px;", ";py;", couleur ";pc;" ; decoupe : ";cg;", ";ch;", ";cd;", ";cb
70 end
8000 ' Rect en q : gauche g, haut h, droite d, bas b (16 bits signes ; droite et bas exclus)
8010 doke q, g & $ffff : doke q + 2, h & $ffff : doke q + 4, d & $ffff : doke q + 6, b & $ffff
8020 return
9000 ' appel 32,f sur l'adresse a (P0-P1) ; erreur dans e
9010 while peek($ff00) : wend : doke $ff04, a
9100 ' appel 32,f, parametres deja poses ; erreur dans e
9110 poke $ff01, f : poke $ff00, 32
9120 while peek($ff00) : wend : e = peek($ff02)
9130 return
9200 ' 32,f en (x, y) : 5 Move To, 11 Line To
9210 while peek($ff00) : wend : doke $ff04, x & $ffff : doke $ff06, y & $ffff : goto 9110
9300 ' 32,4 Set Pen Colour c
9310 while peek($ff00) : wend : poke $ff04, c : f = 4 : goto 9110
9400 ' 32,1 Init Graf
9410 while peek($ff00) : wend : f = 1 : goto 9110
9500 ' 32,6 Get Pen : px, py, pc
9510 while peek($ff00) : wend : f = 6 : gosub 9110
9520 px = deek($ff04) : py = deek($ff06) : pc = peek($ff08)
9530 if px > 32767 then px = px - 65536
9540 if py > 32767 then py = py - 65536
9550 return
9600 ' 32,3 Get Clip dans le Rect k ; valeurs dans cg, ch, cd, cb
9610 a = k : f = 3 : gosub 9000
9620 cg = deek(k) : ch = deek(k + 2) : cd = deek(k + 4) : cb = deek(k + 6)
9630 returnPlume : 0, 0, couleur 15 ; decoupe : 0, 0, 320, 24065C02 assembly (64tass)
; Remettre toute la boîte à outils dans son état de départ (groupe 32, fonction 19, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<b0
ldx #>b0
jsr envoi
lda #<b1
ldx #>b1
jsr envoi
lda #<b2
ldx #>b2
jsr envoi
lda #<b3
ldx #>b3
jsr envoi
lda #<b5
ldx #>b5
jsr envoi
ldx #4
_c4: lda ControlPort+4,x
sta pen,x
dex
bpl _c4
lda #<b6
ldx #>b6
jsr envoi
lda #<t7
ldx #>t7
jsr ecrire
lda pen
ldx pen+1
jsr dec16
lda #<t8
ldx #>t8
jsr ecrire
lda pen+2
ldx pen+2+1
jsr dec16
lda #<t9
ldx #>t9
jsr ecrire
lda pen+4
jsr decimal
lda #<t10
ldx #>t10
jsr ecrire
lda k
ldx k+1
jsr dec16
lda #<t11
ldx #>t11
jsr ecrire
lda k+2
ldx k+2+1
jsr dec16
lda #<t12
ldx #>t12
jsr ecrire
lda k+4
ldx k+4+1
jsr dec16
lda #<t13
ldx #>t13
jsr ecrire
lda k+6
ldx k+6+1
jsr dec16
lda #13
jsr WriteCharacter
rts
q: .word 10, 10, 50, 50 ; gauche, haut, droite, bas (droite et bas exclus)
k: .fill 8
b0: .byte 32, 4, 1, 9 ; un état quelconque : couleur 9...
b1: .byte 32, 5, 4 ; 32,5 : Move To
.word 30, 30
b2: .byte 32, 2, 2 ; ... plume en (30, 30), découpe réduite
.word q
b3: .byte 32, 19, 0 ; Toolbox Reset
b5: .byte 32, 6, 0 ; 32,6 : Get Pen
pen: .fill 5 ; x, y (16 bits), couleur
b6: .byte 32, 3, 2 ; 32,3 : Get Clip
.word k
t7: .text "Plume : ", 0
t8: .text ", ", 0
t9: .text ", couleur ", 0
t10: .text " ; decoupe : ", 0
t11: .text ", ", 0
t12: .text ", ", 0
t13: .text ", ", 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Affiche le mot de 16 bits A (poids faible), X (poids fort) en décimal, sans zéros de tête.
dec16: sta n16
stx n16+1
stz vu
ldy #0 ; puissance de 10 en cours : 10000, 1000, 100, 10
_p: ldx #0 ; chiffre
_s: lda n16
sec
sbc p10l,y
pha
lda n16+1
sbc p10h,y
bcc _neg ; plus petit : chiffre trouvé
sta n16+1
pla
sta n16
inx
bra _s
_neg: pla
txa
ora vu
beq _suiv ; pas de zéro de tête
txa
ora #'0'
phy
jsr WriteCharacter
ply
lda #1
sta vu
_suiv: iny
cpy #4
bne _p
lda n16 ; les unités, toujours
ora #'0'
jmp WriteCharacter
p10l: .byte <10000, <1000, <100, <10
p10h: .byte >10000, >1000, >100, >10
n16: .word 0
vu: .byte 0
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Plume : 0, 0, couleur 15 ; decoupe : 0, 0, 320, 240