Groupe 39 — AGI Pictures Trinity
39,1 Draw Picture · 39,2 Show Picture · 39,3 Picture Duration · 39,4 Read Picture Point · 39,5 Draw Cel · 39,6 Restore Rect · 39,7 Add Cel To Plane · 39,8 Fill Plane Priority
Le groupe 39 décode et affiche les images des jeux Sierra AGI (version 2), l'interface demandée par le portage Neo6502AGI. Une image AGI (ressource PICTURE) est une suite de commandes de dessin : couleur visuelle (F0), priorité (F2), lignes (F6), remplissage (F8), fin (FF). 39,1 la décode dans un plan de 160 × 168 points gardé au début de la mémoire graphique : un octet par point, priorité dans le quartet haut, couleur visuelle (0 à 15) dans le quartet bas. Un plan effacé vaut couleur 15, priorité 4.
39,2 recopie les couleurs du plan à l'écran (320 points de large, chaque point doublé ; modes 8 ou 4 bits par pixel). 39,4 relit un point du plan. 39,5 et 39,6 dessinent et effacent à l'écran les cels des objets animés sans écrire le plan, qui sert au test de priorité : un objet est caché derrière un décor de priorité plus haute. 39,7 et 39,8 écrivent dans le plan (commande add.to.pic).
Les exemples utilisent une image de 21 octets : un rectangle rouge (couleur 12, priorité 9) rempli de jaune (14), de (20, 30) à (100, 80). Ils relisent les points du plan avec 39,4 ou ceux de l'écran avec 5,33. Les images, tuiles et sprites utilisent la même mémoire graphique : un programme qui emploie ce groupe ne doit pas s'en servir. NeoBASIC n'a aucun mot-clé pour ce groupe : l'exemple écrit la boîte aux lettres ($FF00).
39,1 Draw Picture Trinity
Décode une image AGI (ressource PICTURE de Sierra) dans le plan de 160 × 168 points.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse de l'image dans la RAM du 6502 |
P2-P3 | uint16 | longueur de l'image en octets |
P4 | uint8 | bit 0 : effacer le plan avant (priorité 4, couleur 15) |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | 1 adresse hors de la RAM du 6502 ou longueur 0, 2 pile de remplissage pleine |
Le plan est gardé dans la mémoire graphique, un octet par point : priorité dans le quartet haut, couleur visuelle dans le quartet bas. Un plan effacé vaut couleur 15, priorité 4. L'image des exemples (21 octets) trace un rectangle rouge (couleur 12, priorité 9) puis le remplit de jaune (14) : on relit le plan avec 39,4. Sans effacement (bit 0 à 0), une seconde image se dessine par-dessus la première ; avec effacement, elle repart d'un plan vide. La mémoire graphique est partagée avec les sprites, les tuiles et les images : un programme qui utilise ce groupe ne doit pas s'en servir. NeoBASIC n'a pas de mot-clé pour cet appel : l'exemple écrit la boîte aux lettres.
Texte de la documentation du firmware (anglais)
Trinity (T-107). Decodes the Sierra AGI v2 PICTURE resource at address Parameters:0,1 of 6502 RAM, length Parameters:2,3, into the 160x168 AGI plane kept at offset 0 of graphics memory (page $90, 26 880 bytes, one byte per pixel : priority in the high nibble, visual colour in the low nibble). If bit 0 of Parameter:4 is set the plane is first cleared (priority 4, visual 15). Generic : works for any AGI game. The 6502 is held for the whole decoding (a few ms to about 40 ms). Errors : 1 address range outside 6502 RAM or length 0, 2 fill stack overflow. The fill stack uses graphics memory just after the plane (offsets 26 880 to 30 975, 4 096 bytes). Graphics memory is shared with sprites, tiles and images : a program using this group must not use them.
C (llvm-mos)
/* Décoder une image AGI (groupe 39, 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)
;
}
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
/* image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50) */
static const uint8_t img[] = {0xF0, 0x0C, 0xF2, 0x09, 0xF6, 0x14, 0x1E, 0x64, 0x1E, 0x64, 0x50, 0x14, 0x50, 0x14, 0x1E, 0xF0, 0x0E, 0xF8, 0x32, 0x32, 0xFF};
/* seconde image : un seul point de couleur 3 en (90,90) */
static const uint8_t img2[] = {0xF0, 0x03, 0xF6, 0x5A, 0x5A, 0xFF};
int main(void) {
uint8_t e0, c1, p1, c2, p2, c3, p3, c4, p4, c5, p5, c6, p6, c7, p7, e1;
libre();
p16(0, (uint16_t)img);
p16(2, sizeof img);
ControlPort.params[4] = 1;
api(39, 1);
e0 = ControlPort.error;
libre();
ControlPort.params[0] = 20;
ControlPort.params[1] = 30;
api(39, 4);
c1 = ControlPort.params[2];
p1 = ControlPort.params[3];
libre();
ControlPort.params[0] = 50;
ControlPort.params[1] = 50;
api(39, 4);
c2 = ControlPort.params[2];
p2 = ControlPort.params[3];
libre();
ControlPort.params[0] = 5;
ControlPort.params[1] = 5;
api(39, 4);
c3 = ControlPort.params[2];
p3 = ControlPort.params[3];
libre();
p16(0, (uint16_t)img2);
p16(2, sizeof img2);
ControlPort.params[4] = 0;
api(39, 1);
libre();
ControlPort.params[0] = 20;
ControlPort.params[1] = 30;
api(39, 4);
c4 = ControlPort.params[2];
p4 = ControlPort.params[3];
libre();
ControlPort.params[0] = 90;
ControlPort.params[1] = 90;
api(39, 4);
c5 = ControlPort.params[2];
p5 = ControlPort.params[3];
libre();
p16(0, (uint16_t)img2);
p16(2, sizeof img2);
ControlPort.params[4] = 1;
api(39, 1);
libre();
ControlPort.params[0] = 20;
ControlPort.params[1] = 30;
api(39, 4);
c6 = ControlPort.params[2];
p6 = ControlPort.params[3];
libre();
ControlPort.params[0] = 90;
ControlPort.params[1] = 90;
api(39, 4);
c7 = ControlPort.params[2];
p7 = ControlPort.params[3];
libre();
p16(0, (uint16_t)img);
p16(2, 0);
ControlPort.params[4] = 1;
api(39, 1);
e1 = ControlPort.error;
printf("Image : erreur %u\n", e0);
printf("Trait : couleur %u, priorite %u\n", c1, p1);
printf("Interieur : couleur %u, priorite %u\n", c2, p2);
printf("Fond : couleur %u, priorite %u\n", c3, p3);
printf("Sans effacement : trait %u, point %u\n", c4, c5);
printf("Avec effacement : trait %u, point %u\n", c6, c7);
printf("Longueur 0 : erreur %u\n", e1);
return 0;
}Image : erreur 0
Trait : couleur 12, priorite 9
Interieur : couleur 14, priorite 9
Fond : couleur 15, priorite 4
Sans effacement : trait 12, point 3
Avec effacement : trait 15, point 3
Longueur 0 : erreur 1Mad Pascal
// Décoder une image AGI (groupe 39, fonction 1, Trinity).
program agi1;
uses crt, neo6502;
// image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
const img: array[0..20] of byte = ($F0, $0C, $F2, $09, $F6, $14, $1E, $64, $1E, $64, $50, $14, $50, $14, $1E, $F0, $0E, $F8, $32, $32, $FF);
// seconde image : un seul point de couleur 3 en (90,90)
const img2: array[0..5] of byte = ($F0, $03, $F6, $5A, $5A, $FF);
var e0, c1, p1, c2, p2, c3, p3, c4, p4, c5, p5, c6, p6, c7, p7, e1: byte;
procedure p16(i: byte; v: word); // paramètre 16 bits en Pi, Pi+1
begin
NeoMessage.params[i] := lo(v);
NeoMessage.params[i + 1] := hi(v);
end;
procedure appel(g, f: byte); // lance l'appel et attend la fin
begin
NeoSendMessage(g, f);
NeoWaitMessage;
end;
begin
NeoWaitMessage;
p16(0, word(@img));
p16(2, 21);
NeoMessage.params[4] := 1;
appel(39, 1);
e0 := NeoMessage.error;
NeoWaitMessage;
NeoMessage.params[0] := 20;
NeoMessage.params[1] := 30;
appel(39, 4);
c1 := NeoMessage.params[2];
p1 := NeoMessage.params[3];
NeoWaitMessage;
NeoMessage.params[0] := 50;
NeoMessage.params[1] := 50;
appel(39, 4);
c2 := NeoMessage.params[2];
p2 := NeoMessage.params[3];
NeoWaitMessage;
NeoMessage.params[0] := 5;
NeoMessage.params[1] := 5;
appel(39, 4);
c3 := NeoMessage.params[2];
p3 := NeoMessage.params[3];
NeoWaitMessage;
p16(0, word(@img2));
p16(2, 6);
NeoMessage.params[4] := 0;
appel(39, 1);
NeoWaitMessage;
NeoMessage.params[0] := 20;
NeoMessage.params[1] := 30;
appel(39, 4);
c4 := NeoMessage.params[2];
p4 := NeoMessage.params[3];
NeoWaitMessage;
NeoMessage.params[0] := 90;
NeoMessage.params[1] := 90;
appel(39, 4);
c5 := NeoMessage.params[2];
p5 := NeoMessage.params[3];
NeoWaitMessage;
p16(0, word(@img2));
p16(2, 6);
NeoMessage.params[4] := 1;
appel(39, 1);
NeoWaitMessage;
NeoMessage.params[0] := 20;
NeoMessage.params[1] := 30;
appel(39, 4);
c6 := NeoMessage.params[2];
p6 := NeoMessage.params[3];
NeoWaitMessage;
NeoMessage.params[0] := 90;
NeoMessage.params[1] := 90;
appel(39, 4);
c7 := NeoMessage.params[2];
p7 := NeoMessage.params[3];
NeoWaitMessage;
p16(0, word(@img));
p16(2, 0);
NeoMessage.params[4] := 1;
appel(39, 1);
e1 := NeoMessage.error;
writeln('Image : erreur ', e0);
writeln('Trait : couleur ', c1, ', priorite ', p1);
writeln('Interieur : couleur ', c2, ', priorite ', p2);
writeln('Fond : couleur ', c3, ', priorite ', p3);
writeln('Sans effacement : trait ', c4, ', point ', c5);
writeln('Avec effacement : trait ', c6, ', point ', c7);
writeln('Longueur 0 : erreur ', e1);
end.Image : erreur 0
Trait : couleur 12, priorite 9
Interieur : couleur 14, priorite 9
Fond : couleur 15, priorite 4
Sans effacement : trait 12, point 3
Avec effacement : trait 15, point 3
Longueur 0 : erreur 1NeoBASIC
10 ' Décoder une image AGI (groupe 39, fonction 1, Trinity)
20 ' image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
30 di = alloc(21)
40 poke di + 0, 240 : poke di + 1, 12 : poke di + 2, 242 : poke di + 3, 9 : poke di + 4, 246 : poke di + 5, 20
50 poke di + 6, 30 : poke di + 7, 100 : poke di + 8, 30 : poke di + 9, 100 : poke di + 10, 80 : poke di + 11, 20
60 poke di + 12, 80 : poke di + 13, 20 : poke di + 14, 30 : poke di + 15, 240 : poke di + 16, 14 : poke di + 17, 248
70 poke di + 18, 50 : poke di + 19, 50 : poke di + 20, 255
80 ' seconde image : un seul point de couleur 3 en (90,90)
90 dj = alloc(6)
100 poke dj + 0, 240 : poke dj + 1, 3 : poke dj + 2, 246 : poke dj + 3, 90 : poke dj + 4, 90 : poke dj + 5, 255
110 while peek($ff00) : wend : doke $ff04 + 0, di : doke $ff04 + 2, 21 : poke $ff04 + 4, 1 : f = 1 : gosub 8100
120 e0 = e
130 while peek($ff00) : wend : poke $ff04 + 0, 20 : poke $ff04 + 1, 30 : f = 4 : gosub 8100
140 c1 = peek($ff04 + 2)
150 p1 = peek($ff04 + 3)
160 while peek($ff00) : wend : poke $ff04 + 0, 50 : poke $ff04 + 1, 50 : f = 4 : gosub 8100
170 c2 = peek($ff04 + 2)
180 p2 = peek($ff04 + 3)
190 while peek($ff00) : wend : poke $ff04 + 0, 5 : poke $ff04 + 1, 5 : f = 4 : gosub 8100
200 c3 = peek($ff04 + 2)
210 p3 = peek($ff04 + 3)
220 while peek($ff00) : wend : doke $ff04 + 0, dj : doke $ff04 + 2, 6 : poke $ff04 + 4, 0 : f = 1 : gosub 8100
230 while peek($ff00) : wend : poke $ff04 + 0, 20 : poke $ff04 + 1, 30 : f = 4 : gosub 8100
240 c4 = peek($ff04 + 2)
250 p4 = peek($ff04 + 3)
260 while peek($ff00) : wend : poke $ff04 + 0, 90 : poke $ff04 + 1, 90 : f = 4 : gosub 8100
270 c5 = peek($ff04 + 2)
280 p5 = peek($ff04 + 3)
290 while peek($ff00) : wend : doke $ff04 + 0, dj : doke $ff04 + 2, 6 : poke $ff04 + 4, 1 : f = 1 : gosub 8100
300 while peek($ff00) : wend : poke $ff04 + 0, 20 : poke $ff04 + 1, 30 : f = 4 : gosub 8100
310 c6 = peek($ff04 + 2)
320 p6 = peek($ff04 + 3)
330 while peek($ff00) : wend : poke $ff04 + 0, 90 : poke $ff04 + 1, 90 : f = 4 : gosub 8100
340 c7 = peek($ff04 + 2)
350 p7 = peek($ff04 + 3)
360 while peek($ff00) : wend : doke $ff04 + 0, di : doke $ff04 + 2, 0 : poke $ff04 + 4, 1 : f = 1 : gosub 8100
370 e1 = e
380 print "Image : erreur ";e0
390 print "Trait : couleur ";c1;", priorite ";p1
400 print "Interieur : couleur ";c2;", priorite ";p2
410 print "Fond : couleur ";c3;", priorite ";p3
420 print "Sans effacement : trait ";c4;", point ";c5
430 print "Avec effacement : trait ";c6;", point ";c7
440 print "Longueur 0 : erreur ";e1
450 end
8100 ' appel 39,f, parametres deja poses ; erreur dans e
8105 g = 39
8110 poke $ff01, f : poke $ff00, g
8120 while peek($ff00) : wend : e = peek($ff02) : returnImage : erreur 0
Trait : couleur 12, priorite 9
Interieur : couleur 14, priorite 9
Fond : couleur 15, priorite 4
Sans effacement : trait 12, point 3
Avec effacement : trait 15, point 3
Longueur 0 : erreur 1Assembleur 65C02 (64tass)
; Décoder une image AGI (groupe 39, 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:
jsr WaitMessage
lda #<img
sta ControlPort+4
lda #>img
sta ControlPort+5
lda #<(fimg-img)
sta ControlPort+6
lda #>(fimg-img)
sta ControlPort+7
lda #1
sta ControlPort+8
lda #39
ldx #1
jsr appel
lda ControlPort+2
sta e0
jsr WaitMessage
lda #20
sta ControlPort+4
lda #30
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c1
lda ControlPort+7
sta p1
jsr WaitMessage
lda #50
sta ControlPort+4
lda #50
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c2
lda ControlPort+7
sta p2
jsr WaitMessage
lda #5
sta ControlPort+4
lda #5
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c3
lda ControlPort+7
sta p3
jsr WaitMessage
lda #<img2
sta ControlPort+4
lda #>img2
sta ControlPort+5
lda #<(fimg2-img2)
sta ControlPort+6
lda #>(fimg2-img2)
sta ControlPort+7
stz ControlPort+8
lda #39
ldx #1
jsr appel
jsr WaitMessage
lda #20
sta ControlPort+4
lda #30
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c4
lda ControlPort+7
sta p4
jsr WaitMessage
lda #90
sta ControlPort+4
lda #90
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c5
lda ControlPort+7
sta p5
jsr WaitMessage
lda #<img2
sta ControlPort+4
lda #>img2
sta ControlPort+5
lda #<(fimg2-img2)
sta ControlPort+6
lda #>(fimg2-img2)
sta ControlPort+7
lda #1
sta ControlPort+8
lda #39
ldx #1
jsr appel
jsr WaitMessage
lda #20
sta ControlPort+4
lda #30
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c6
lda ControlPort+7
sta p6
jsr WaitMessage
lda #90
sta ControlPort+4
lda #90
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c7
lda ControlPort+7
sta p7
jsr WaitMessage
lda #<img
sta ControlPort+4
lda #>img
sta ControlPort+5
lda #<0
sta ControlPort+6
lda #>0
sta ControlPort+7
lda #1
sta ControlPort+8
lda #39
ldx #1
jsr appel
lda ControlPort+2
sta e1
lda #<t0
ldx #>t0
jsr ecrire
lda e0
jsr decimal
lda #13
jsr WriteCharacter
lda #<t1
ldx #>t1
jsr ecrire
lda c1
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda p1
jsr decimal
lda #13
jsr WriteCharacter
lda #<t3
ldx #>t3
jsr ecrire
lda c2
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda p2
jsr decimal
lda #13
jsr WriteCharacter
lda #<t4
ldx #>t4
jsr ecrire
lda c3
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda p3
jsr decimal
lda #13
jsr WriteCharacter
lda #<t5
ldx #>t5
jsr ecrire
lda c4
jsr decimal
lda #<t6
ldx #>t6
jsr ecrire
lda c5
jsr decimal
lda #13
jsr WriteCharacter
lda #<t7
ldx #>t7
jsr ecrire
lda c6
jsr decimal
lda #<t6
ldx #>t6
jsr ecrire
lda c7
jsr decimal
lda #13
jsr WriteCharacter
lda #<t8
ldx #>t8
jsr ecrire
lda e1
jsr decimal
lda #13
jsr WriteCharacter
rts
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
; image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
img:
.byte $F0, $0C, $F2, $09, $F6, $14, $1E, $64
.byte $1E, $64, $50, $14, $50, $14, $1E, $F0
.byte $0E, $F8, $32, $32, $FF
fimg:
; seconde image : un seul point de couleur 3 en (90,90)
img2:
.byte $F0, $03, $F6, $5A, $5A, $FF
fimg2:
e0: .byte 0
c1: .byte 0
p1: .byte 0
c2: .byte 0
p2: .byte 0
c3: .byte 0
p3: .byte 0
c4: .byte 0
p4: .byte 0
c5: .byte 0
p5: .byte 0
c6: .byte 0
p6: .byte 0
c7: .byte 0
p7: .byte 0
e1: .byte 0
t0: .text "Image : erreur ", 0
t1: .text "Trait : couleur ", 0
t2: .text ", priorite ", 0
t3: .text "Interieur : couleur ", 0
t4: .text "Fond : couleur ", 0
t5: .text "Sans effacement : trait ", 0
t6: .text ", point ", 0
t7: .text "Avec effacement : trait ", 0
t8: .text "Longueur 0 : erreur ", 0Image : erreur 0
Trait : couleur 12, priorite 9
Interieur : couleur 14, priorite 9
Fond : couleur 15, priorite 4
Sans effacement : trait 12, point 3
Avec effacement : trait 15, point 3
Longueur 0 : erreur 139,2 Show Picture Trinity
Copie les couleurs de l'image AGI à l'écran, chaque point doublé en largeur (320 × 168).
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | uint16 | ligne de l'écran où poser le haut de l'image |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | 1 si le mode n'est pas de 320 points de large en 8 ou 4 bits, ou si l'image ne tient pas |
Seules les couleurs (0 à 15) sont copiées, la palette n'est pas changée. L'exemple montre l'image à la ligne 72 du mode 0 (72 + 168 = 240) et relit l'écran avec 5,33 : le point (20, 30) de l'image occupe les pixels 40 et 41 de la ligne 102, le point (19, 30) les pixels 38 et 39. À la ligne 100, l'image déborde de l'écran : erreur 1. NeoBASIC n'a pas de mot-clé pour cet appel : l'exemple écrit la boîte aux lettres.
Texte de la documentation du firmware (anglais)
Copies the visual colours (0-15) of the AGI plane to the screen draw page, from line Parameters:0,1, each pixel doubled in width (320 x 168). Modes 320 pixels wide with 8 or 4 bits per pixel. The palette is not changed. Error 1 if the mode is not supported or the picture does not fit.
C (llvm-mos)
/* Montrer l'image AGI à l'écran (groupe 39, 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)
;
}
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
/* image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50) */
static const uint8_t img[] = {0xF0, 0x0C, 0xF2, 0x09, 0xF6, 0x14, 0x1E, 0x64, 0x1E, 0x64, 0x50, 0x14, 0x50, 0x14, 0x1E, 0xF0, 0x0E, 0xF8, 0x32, 0x32, 0xFF};
int main(void) {
uint8_t e0, a1, a2, a3, a4, e1;
putchar(12); /* efface l'écran avant toute mesure */
libre();
p16(0, (uint16_t)img);
p16(2, sizeof img);
ControlPort.params[4] = 1;
api(39, 1);
libre();
p16(0, 72);
api(39, 2);
e0 = ControlPort.error;
libre(); p16(0, 40); p16(2, 102); api(5, 33); a1 = ControlPort.params[0]; /* 5,33 : Read Pixel */
libre(); p16(0, 41); p16(2, 102); api(5, 33); a2 = ControlPort.params[0]; /* 5,33 : Read Pixel */
libre(); p16(0, 38); p16(2, 102); api(5, 33); a3 = ControlPort.params[0]; /* 5,33 : Read Pixel */
libre(); p16(0, 100); p16(2, 122); api(5, 33); a4 = ControlPort.params[0]; /* 5,33 : Read Pixel */
libre();
p16(0, 100);
api(39, 2);
e1 = ControlPort.error;
printf("Montrer : erreur %u\n", e0);
printf("Trait : %u %u, a gauche : %u\n", a1, a2, a3);
printf("Interieur : %u\n", a4);
printf("Ligne 100 : erreur %u\n", e1);
return 0;
}Montrer : erreur 0
Trait : 12 12, a gauche : 15
Interieur : 14
Ligne 100 : erreur 1Mad Pascal
// Montrer l'image AGI à l'écran (groupe 39, fonction 2, Trinity).
program agi2;
uses crt, neo6502;
// image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
const img: array[0..20] of byte = ($F0, $0C, $F2, $09, $F6, $14, $1E, $64, $1E, $64, $50, $14, $50, $14, $1E, $F0, $0E, $F8, $32, $32, $FF);
var e0, a1, a2, a3, a4, e1: byte;
procedure p16(i: byte; v: word); // paramètre 16 bits en Pi, Pi+1
begin
NeoMessage.params[i] := lo(v);
NeoMessage.params[i + 1] := hi(v);
end;
procedure appel(g, f: byte); // lance l'appel et attend la fin
begin
NeoSendMessage(g, f);
NeoWaitMessage;
end;
begin
write(chr(12)); // efface l'écran avant toute mesure
NeoWaitMessage;
p16(0, word(@img));
p16(2, 21);
NeoMessage.params[4] := 1;
appel(39, 1);
NeoWaitMessage;
p16(0, 72);
appel(39, 2);
e0 := NeoMessage.error;
NeoWaitMessage; p16(0, 40); p16(2, 102); appel(5, 33); a1 := NeoMessage.params[0]; // 5,33 : Read Pixel
NeoWaitMessage; p16(0, 41); p16(2, 102); appel(5, 33); a2 := NeoMessage.params[0]; // 5,33 : Read Pixel
NeoWaitMessage; p16(0, 38); p16(2, 102); appel(5, 33); a3 := NeoMessage.params[0]; // 5,33 : Read Pixel
NeoWaitMessage; p16(0, 100); p16(2, 122); appel(5, 33); a4 := NeoMessage.params[0]; // 5,33 : Read Pixel
NeoWaitMessage;
p16(0, 100);
appel(39, 2);
e1 := NeoMessage.error;
writeln('Montrer : erreur ', e0);
writeln('Trait : ', a1, ' ', a2, ', a gauche : ', a3);
writeln('Interieur : ', a4);
writeln('Ligne 100 : erreur ', e1);
end.Montrer : erreur 0
Trait : 12 12, a gauche : 15
Interieur : 14
Ligne 100 : erreur 1NeoBASIC
10 ' Montrer l'image AGI à l'écran (groupe 39, fonction 2, Trinity)
20 ' image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
30 di = alloc(21)
40 poke di + 0, 240 : poke di + 1, 12 : poke di + 2, 242 : poke di + 3, 9 : poke di + 4, 246 : poke di + 5, 20
50 poke di + 6, 30 : poke di + 7, 100 : poke di + 8, 30 : poke di + 9, 100 : poke di + 10, 80 : poke di + 11, 20
60 poke di + 12, 80 : poke di + 13, 20 : poke di + 14, 30 : poke di + 15, 240 : poke di + 16, 14 : poke di + 17, 248
70 poke di + 18, 50 : poke di + 19, 50 : poke di + 20, 255
80 cls
90 while peek($ff00) : wend : doke $ff04 + 0, di : doke $ff04 + 2, 21 : poke $ff04 + 4, 1 : f = 1 : gosub 8100
100 while peek($ff00) : wend : doke $ff04 + 0, 72 : f = 2 : gosub 8100
110 e0 = e
120 while peek($ff00) : wend : doke $ff04, 40 : doke $ff06, 102 : f = 33 : g = 5 : gosub 8110 : a1 = peek($ff04)
130 while peek($ff00) : wend : doke $ff04, 41 : doke $ff06, 102 : f = 33 : g = 5 : gosub 8110 : a2 = peek($ff04)
140 while peek($ff00) : wend : doke $ff04, 38 : doke $ff06, 102 : f = 33 : g = 5 : gosub 8110 : a3 = peek($ff04)
150 while peek($ff00) : wend : doke $ff04, 100 : doke $ff06, 122 : f = 33 : g = 5 : gosub 8110 : a4 = peek($ff04)
160 while peek($ff00) : wend : doke $ff04 + 0, 100 : f = 2 : gosub 8100
170 e1 = e
180 print "Montrer : erreur ";e0
190 print "Trait : ";a1;" ";a2;", a gauche : ";a3
200 print "Interieur : ";a4
210 print "Ligne 100 : erreur ";e1
220 end
8100 ' appel 39,f, parametres deja poses ; erreur dans e
8105 g = 39
8110 poke $ff01, f : poke $ff00, g
8120 while peek($ff00) : wend : e = peek($ff02) : returnMontrer : erreur 0
Trait : 12 12, a gauche : 15
Interieur : 14
Ligne 100 : erreur 1Assembleur 65C02 (64tass)
; Montrer l'image AGI à l'écran (groupe 39, 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 ; efface l'écran avant toute mesure
jsr WriteCharacter
jsr WaitMessage
lda #<img
sta ControlPort+4
lda #>img
sta ControlPort+5
lda #<(fimg-img)
sta ControlPort+6
lda #>(fimg-img)
sta ControlPort+7
lda #1
sta ControlPort+8
lda #39
ldx #1
jsr appel
jsr WaitMessage
lda #<72
sta ControlPort+4
lda #>72
sta ControlPort+5
lda #39
ldx #2
jsr appel
lda ControlPort+2
sta e0
jsr WaitMessage
lda #<40
sta ControlPort+4
lda #>40
sta ControlPort+5
lda #<102
sta ControlPort+6
lda #>102
sta ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
sta a1
jsr WaitMessage
lda #<41
sta ControlPort+4
lda #>41
sta ControlPort+5
lda #<102
sta ControlPort+6
lda #>102
sta ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
sta a2
jsr WaitMessage
lda #<38
sta ControlPort+4
lda #>38
sta ControlPort+5
lda #<102
sta ControlPort+6
lda #>102
sta ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
sta a3
jsr WaitMessage
lda #<100
sta ControlPort+4
lda #>100
sta ControlPort+5
lda #<122
sta ControlPort+6
lda #>122
sta ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
sta a4
jsr WaitMessage
lda #<100
sta ControlPort+4
lda #>100
sta ControlPort+5
lda #39
ldx #2
jsr appel
lda ControlPort+2
sta e1
lda #<t0
ldx #>t0
jsr ecrire
lda e0
jsr decimal
lda #13
jsr WriteCharacter
lda #<t1
ldx #>t1
jsr ecrire
lda a1
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda a2
jsr decimal
lda #<t3
ldx #>t3
jsr ecrire
lda a3
jsr decimal
lda #13
jsr WriteCharacter
lda #<t4
ldx #>t4
jsr ecrire
lda a4
jsr decimal
lda #13
jsr WriteCharacter
lda #<t5
ldx #>t5
jsr ecrire
lda e1
jsr decimal
lda #13
jsr WriteCharacter
rts
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
; image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
img:
.byte $F0, $0C, $F2, $09, $F6, $14, $1E, $64
.byte $1E, $64, $50, $14, $50, $14, $1E, $F0
.byte $0E, $F8, $32, $32, $FF
fimg:
e0: .byte 0
a1: .byte 0
a2: .byte 0
a3: .byte 0
a4: .byte 0
e1: .byte 0
t0: .text "Montrer : erreur ", 0
t1: .text "Trait : ", 0
t2: .text " ", 0
t3: .text ", a gauche : ", 0
t4: .text "Interieur : ", 0
t5: .text "Ligne 100 : erreur ", 0Montrer : erreur 0
Trait : 12 12, a gauche : 15
Interieur : 14
Ligne 100 : erreur 139,3 Picture Duration Trinity
Donne la durée du dernier décodage d'image, en microsecondes.
Entrées : aucune.
| Octets | Type | Rôle |
|---|---|---|
P0-P3 | uint32 | durée de 39,1 en microsecondes (0 sur les émulateurs) |
La durée n'est mesurée que sur la carte : les émulateurs répondent 0, c'est ce que l'exemple affiche (les quatre octets P0 à P3). Sur la carte, comptez de quelques millisecondes à une quarantaine selon l'image. NeoBASIC n'a pas de mot-clé pour cet appel : l'exemple écrit la boîte aux lettres.
Texte de la documentation du firmware (anglais)
Returns in Parameters:0-3 the duration of the last Draw Picture in microseconds (board only, 0 on the emulators).
C (llvm-mos)
/* Durée du décodage d'une image AGI (groupe 39, 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)
;
}
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
/* image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50) */
static const uint8_t img[] = {0xF0, 0x0C, 0xF2, 0x09, 0xF6, 0x14, 0x1E, 0x64, 0x1E, 0x64, 0x50, 0x14, 0x50, 0x14, 0x1E, 0xF0, 0x0E, 0xF8, 0x32, 0x32, 0xFF};
int main(void) {
uint8_t d0, d1, d2, d3;
libre();
p16(0, (uint16_t)img);
p16(2, sizeof img);
ControlPort.params[4] = 1;
api(39, 1);
libre();
api(39, 3);
d0 = ControlPort.params[0];
d1 = ControlPort.params[1];
d2 = ControlPort.params[2];
d3 = ControlPort.params[3];
printf("Duree : %u %u %u %u\n", d0, d1, d2, d3);
return 0;
}Duree : 0 0 0 0Mad Pascal
// Durée du décodage d'une image AGI (groupe 39, fonction 3, Trinity).
program agi3;
uses crt, neo6502;
// image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
const img: array[0..20] of byte = ($F0, $0C, $F2, $09, $F6, $14, $1E, $64, $1E, $64, $50, $14, $50, $14, $1E, $F0, $0E, $F8, $32, $32, $FF);
var d0, d1, d2, d3: byte;
procedure p16(i: byte; v: word); // paramètre 16 bits en Pi, Pi+1
begin
NeoMessage.params[i] := lo(v);
NeoMessage.params[i + 1] := hi(v);
end;
procedure appel(g, f: byte); // lance l'appel et attend la fin
begin
NeoSendMessage(g, f);
NeoWaitMessage;
end;
begin
NeoWaitMessage;
p16(0, word(@img));
p16(2, 21);
NeoMessage.params[4] := 1;
appel(39, 1);
NeoWaitMessage;
appel(39, 3);
d0 := NeoMessage.params[0];
d1 := NeoMessage.params[1];
d2 := NeoMessage.params[2];
d3 := NeoMessage.params[3];
writeln('Duree : ', d0, ' ', d1, ' ', d2, ' ', d3);
end.Duree : 0 0 0 0NeoBASIC
10 ' Durée du décodage d'une image AGI (groupe 39, fonction 3, Trinity)
20 ' image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
30 di = alloc(21)
40 poke di + 0, 240 : poke di + 1, 12 : poke di + 2, 242 : poke di + 3, 9 : poke di + 4, 246 : poke di + 5, 20
50 poke di + 6, 30 : poke di + 7, 100 : poke di + 8, 30 : poke di + 9, 100 : poke di + 10, 80 : poke di + 11, 20
60 poke di + 12, 80 : poke di + 13, 20 : poke di + 14, 30 : poke di + 15, 240 : poke di + 16, 14 : poke di + 17, 248
70 poke di + 18, 50 : poke di + 19, 50 : poke di + 20, 255
80 while peek($ff00) : wend : doke $ff04 + 0, di : doke $ff04 + 2, 21 : poke $ff04 + 4, 1 : f = 1 : gosub 8100
90 while peek($ff00) : wend : f = 3 : gosub 8100
100 d0 = peek($ff04 + 0)
110 d1 = peek($ff04 + 1)
120 d2 = peek($ff04 + 2)
130 d3 = peek($ff04 + 3)
140 print "Duree : ";d0;" ";d1;" ";d2;" ";d3
150 end
8100 ' appel 39,f, parametres deja poses ; erreur dans e
8105 g = 39
8110 poke $ff01, f : poke $ff00, g
8120 while peek($ff00) : wend : e = peek($ff02) : returnDuree : 0 0 0 0Assembleur 65C02 (64tass)
; Durée du décodage d'une image AGI (groupe 39, 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:
jsr WaitMessage
lda #<img
sta ControlPort+4
lda #>img
sta ControlPort+5
lda #<(fimg-img)
sta ControlPort+6
lda #>(fimg-img)
sta ControlPort+7
lda #1
sta ControlPort+8
lda #39
ldx #1
jsr appel
jsr WaitMessage
lda #39
ldx #3
jsr appel
lda ControlPort+4
sta d0
lda ControlPort+5
sta d1
lda ControlPort+6
sta d2
lda ControlPort+7
sta d3
lda #<t0
ldx #>t0
jsr ecrire
lda d0
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
lda d1
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
lda d2
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
lda d3
jsr decimal
lda #13
jsr WriteCharacter
rts
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
; image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
img:
.byte $F0, $0C, $F2, $09, $F6, $14, $1E, $64
.byte $1E, $64, $50, $14, $50, $14, $1E, $F0
.byte $0E, $F8, $32, $32, $FF
fimg:
d0: .byte 0
d1: .byte 0
d2: .byte 0
d3: .byte 0
t0: .text "Duree : ", 0
t1: .text " ", 0Duree : 0 0 0 039,4 Read Picture Point Trinity
Lit la couleur et la priorité d'un point du plan AGI.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | X (0 à 159) |
P1 | uint8 | Y (0 à 167) |
| Octets | Type | Rôle |
|---|---|---|
P2 | uint8 | couleur visuelle (0 à 15) |
P3 | uint8 | priorité (0 à 15) |
erreur | uint8 | 1 si le point est hors du plan |
Les coordonnées sont celles du plan (160 × 168), pas celles de l'écran. Hors du plan, l'erreur est 1 et P2, P3 ne sont pas changés. NeoBASIC n'a pas de mot-clé pour cet appel : l'exemple écrit la boîte aux lettres.
Texte de la documentation du firmware (anglais)
Returns the visual colour (Parameter:2) and the priority (Parameter:3) of the point Parameter:0, Parameter:1 (X 0-159, Y 0-167) of the AGI plane. Error 1 if out of range.
C (llvm-mos)
/* Lire un point du plan AGI (groupe 39, 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)
;
}
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
/* image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50) */
static const uint8_t img[] = {0xF0, 0x0C, 0xF2, 0x09, 0xF6, 0x14, 0x1E, 0x64, 0x1E, 0x64, 0x50, 0x14, 0x50, 0x14, 0x1E, 0xF0, 0x0E, 0xF8, 0x32, 0x32, 0xFF};
int main(void) {
uint8_t c1, p1, c2, p2, c3, p3, c4, p4, e1, c5, p5, e2;
libre();
p16(0, (uint16_t)img);
p16(2, sizeof img);
ControlPort.params[4] = 1;
api(39, 1);
libre();
ControlPort.params[0] = 20;
ControlPort.params[1] = 30;
api(39, 4);
c1 = ControlPort.params[2];
p1 = ControlPort.params[3];
libre();
ControlPort.params[0] = 50;
ControlPort.params[1] = 50;
api(39, 4);
c2 = ControlPort.params[2];
p2 = ControlPort.params[3];
libre();
ControlPort.params[0] = 5;
ControlPort.params[1] = 5;
api(39, 4);
c3 = ControlPort.params[2];
p3 = ControlPort.params[3];
libre();
ControlPort.params[0] = 160;
ControlPort.params[1] = 0;
api(39, 4);
c4 = ControlPort.params[2];
p4 = ControlPort.params[3];
e1 = ControlPort.error;
libre();
ControlPort.params[0] = 0;
ControlPort.params[1] = 168;
api(39, 4);
c5 = ControlPort.params[2];
p5 = ControlPort.params[3];
e2 = ControlPort.error;
printf("Trait (20, 30) : couleur %u, priorite %u\n", c1, p1);
printf("Dedans (50, 50) : couleur %u, priorite %u\n", c2, p2);
printf("Fond (5, 5) : couleur %u, priorite %u\n", c3, p3);
printf("X = 160 : erreur %u ; Y = 168 : erreur %u\n", e1, e2);
return 0;
}Trait (20, 30) : couleur 12, priorite 9
Dedans (50, 50) : couleur 14, priorite 9
Fond (5, 5) : couleur 15, priorite 4
X = 160 : erreur 1 ; Y = 168 : erreur 1Mad Pascal
// Lire un point du plan AGI (groupe 39, fonction 4, Trinity).
program agi4;
uses crt, neo6502;
// image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
const img: array[0..20] of byte = ($F0, $0C, $F2, $09, $F6, $14, $1E, $64, $1E, $64, $50, $14, $50, $14, $1E, $F0, $0E, $F8, $32, $32, $FF);
var c1, p1, c2, p2, c3, p3, c4, p4, e1, c5, p5, e2: byte;
procedure p16(i: byte; v: word); // paramètre 16 bits en Pi, Pi+1
begin
NeoMessage.params[i] := lo(v);
NeoMessage.params[i + 1] := hi(v);
end;
procedure appel(g, f: byte); // lance l'appel et attend la fin
begin
NeoSendMessage(g, f);
NeoWaitMessage;
end;
begin
NeoWaitMessage;
p16(0, word(@img));
p16(2, 21);
NeoMessage.params[4] := 1;
appel(39, 1);
NeoWaitMessage;
NeoMessage.params[0] := 20;
NeoMessage.params[1] := 30;
appel(39, 4);
c1 := NeoMessage.params[2];
p1 := NeoMessage.params[3];
NeoWaitMessage;
NeoMessage.params[0] := 50;
NeoMessage.params[1] := 50;
appel(39, 4);
c2 := NeoMessage.params[2];
p2 := NeoMessage.params[3];
NeoWaitMessage;
NeoMessage.params[0] := 5;
NeoMessage.params[1] := 5;
appel(39, 4);
c3 := NeoMessage.params[2];
p3 := NeoMessage.params[3];
NeoWaitMessage;
NeoMessage.params[0] := 160;
NeoMessage.params[1] := 0;
appel(39, 4);
c4 := NeoMessage.params[2];
p4 := NeoMessage.params[3];
e1 := NeoMessage.error;
NeoWaitMessage;
NeoMessage.params[0] := 0;
NeoMessage.params[1] := 168;
appel(39, 4);
c5 := NeoMessage.params[2];
p5 := NeoMessage.params[3];
e2 := NeoMessage.error;
writeln('Trait (20, 30) : couleur ', c1, ', priorite ', p1);
writeln('Dedans (50, 50) : couleur ', c2, ', priorite ', p2);
writeln('Fond (5, 5) : couleur ', c3, ', priorite ', p3);
writeln('X = 160 : erreur ', e1, ' ; Y = 168 : erreur ', e2);
end.Trait (20, 30) : couleur 12, priorite 9
Dedans (50, 50) : couleur 14, priorite 9
Fond (5, 5) : couleur 15, priorite 4
X = 160 : erreur 1 ; Y = 168 : erreur 1NeoBASIC
10 ' Lire un point du plan AGI (groupe 39, fonction 4, Trinity)
20 ' image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
30 di = alloc(21)
40 poke di + 0, 240 : poke di + 1, 12 : poke di + 2, 242 : poke di + 3, 9 : poke di + 4, 246 : poke di + 5, 20
50 poke di + 6, 30 : poke di + 7, 100 : poke di + 8, 30 : poke di + 9, 100 : poke di + 10, 80 : poke di + 11, 20
60 poke di + 12, 80 : poke di + 13, 20 : poke di + 14, 30 : poke di + 15, 240 : poke di + 16, 14 : poke di + 17, 248
70 poke di + 18, 50 : poke di + 19, 50 : poke di + 20, 255
80 while peek($ff00) : wend : doke $ff04 + 0, di : doke $ff04 + 2, 21 : poke $ff04 + 4, 1 : f = 1 : gosub 8100
90 while peek($ff00) : wend : poke $ff04 + 0, 20 : poke $ff04 + 1, 30 : f = 4 : gosub 8100
100 c1 = peek($ff04 + 2)
110 p1 = peek($ff04 + 3)
120 while peek($ff00) : wend : poke $ff04 + 0, 50 : poke $ff04 + 1, 50 : f = 4 : gosub 8100
130 c2 = peek($ff04 + 2)
140 p2 = peek($ff04 + 3)
150 while peek($ff00) : wend : poke $ff04 + 0, 5 : poke $ff04 + 1, 5 : f = 4 : gosub 8100
160 c3 = peek($ff04 + 2)
170 p3 = peek($ff04 + 3)
180 while peek($ff00) : wend : poke $ff04 + 0, 160 : poke $ff04 + 1, 0 : f = 4 : gosub 8100
190 c4 = peek($ff04 + 2)
200 p4 = peek($ff04 + 3)
210 e1 = e
220 while peek($ff00) : wend : poke $ff04 + 0, 0 : poke $ff04 + 1, 168 : f = 4 : gosub 8100
230 c5 = peek($ff04 + 2)
240 p5 = peek($ff04 + 3)
250 e2 = e
260 print "Trait (20, 30) : couleur ";c1;", priorite ";p1
270 print "Dedans (50, 50) : couleur ";c2;", priorite ";p2
280 print "Fond (5, 5) : couleur ";c3;", priorite ";p3
290 print "X = 160 : erreur ";e1;" ; Y = 168 : erreur ";e2
300 end
8100 ' appel 39,f, parametres deja poses ; erreur dans e
8105 g = 39
8110 poke $ff01, f : poke $ff00, g
8120 while peek($ff00) : wend : e = peek($ff02) : returnTrait (20, 30) : couleur 12, priorite 9
Dedans (50, 50) : couleur 14, priorite 9
Fond (5, 5) : couleur 15, priorite 4
X = 160 : erreur 1 ; Y = 168 : erreur 1Assembleur 65C02 (64tass)
; Lire un point du plan AGI (groupe 39, 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:
jsr WaitMessage
lda #<img
sta ControlPort+4
lda #>img
sta ControlPort+5
lda #<(fimg-img)
sta ControlPort+6
lda #>(fimg-img)
sta ControlPort+7
lda #1
sta ControlPort+8
lda #39
ldx #1
jsr appel
jsr WaitMessage
lda #20
sta ControlPort+4
lda #30
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c1
lda ControlPort+7
sta p1
jsr WaitMessage
lda #50
sta ControlPort+4
lda #50
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c2
lda ControlPort+7
sta p2
jsr WaitMessage
lda #5
sta ControlPort+4
lda #5
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c3
lda ControlPort+7
sta p3
jsr WaitMessage
lda #160
sta ControlPort+4
stz ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c4
lda ControlPort+7
sta p4
lda ControlPort+2
sta e1
jsr WaitMessage
stz ControlPort+4
lda #168
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c5
lda ControlPort+7
sta p5
lda ControlPort+2
sta e2
lda #<t0
ldx #>t0
jsr ecrire
lda c1
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
lda p1
jsr decimal
lda #13
jsr WriteCharacter
lda #<t2
ldx #>t2
jsr ecrire
lda c2
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
lda p2
jsr decimal
lda #13
jsr WriteCharacter
lda #<t3
ldx #>t3
jsr ecrire
lda c3
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
lda p3
jsr decimal
lda #13
jsr WriteCharacter
lda #<t4
ldx #>t4
jsr ecrire
lda e1
jsr decimal
lda #<t5
ldx #>t5
jsr ecrire
lda e2
jsr decimal
lda #13
jsr WriteCharacter
rts
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
; image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
img:
.byte $F0, $0C, $F2, $09, $F6, $14, $1E, $64
.byte $1E, $64, $50, $14, $50, $14, $1E, $F0
.byte $0E, $F8, $32, $32, $FF
fimg:
c1: .byte 0
p1: .byte 0
c2: .byte 0
p2: .byte 0
c3: .byte 0
p3: .byte 0
c4: .byte 0
p4: .byte 0
e1: .byte 0
c5: .byte 0
p5: .byte 0
e2: .byte 0
t0: .text "Trait (20, 30) : couleur ", 0
t1: .text ", priorite ", 0
t2: .text "Dedans (50, 50) : couleur ", 0
t3: .text "Fond (5, 5) : couleur ", 0
t4: .text "X = 160 : erreur ", 0
t5: .text " ; Y = 168 : erreur ", 0Trait (20, 30) : couleur 12, priorite 9
Dedans (50, 50) : couleur 14, priorite 9
Fond (5, 5) : couleur 15, priorite 4
X = 160 : erreur 1 ; Y = 168 : erreur 139,5 Draw Cel Trinity
Dessine à l'écran un cel de vue AGI, sans toucher au plan.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse de l'en-tête du cel dans la RAM du 6502 |
P2 | uint8 | X du côté gauche |
P3 | uint8 | Y de la ligne du bas |
P4 | uint8 | priorité de l'objet |
P5 | uint8 | bit 0 : retourner horizontalement |
P6-P7 | uint16 | ligne de l'écran où est le haut du plan |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | 1 cel vide, position hors du plan, en-tête hors de la RAM ou mode non géré ; 2 données du cel coupées par la fin de la RAM |
Le cel commence par sa largeur, sa hauteur et un octet au format PC (bit 7 miroir, bits 6 à 4 boucle, quartet bas : couleur transparente) ; suivent les lignes, une suite d'octets « couleur dans le quartet haut, longueur dans le quartet bas », 0 en fin de ligne. Un point est dessiné s'il n'est pas transparent et si la priorité de l'objet est supérieure ou égale à celle du plan à cet endroit. Le plan n'est jamais écrit. L'exemple dessine le cel de 4 × 2 points en priorité 12 sur l'intérieur du rectangle (priorité 9) : il est visible, le point transparent laisse voir le jaune. En priorité 5 il est caché, et le plan reste 14 / 9. NeoBASIC n'a pas de mot-clé pour cet appel : l'exemple écrit la boîte aux lettres.
Texte de la documentation du firmware (anglais)
Trinity (T-109). Draws the AGI view cel whose header (width, height, then a byte in PC format : bit 7 mirror, bits 6-4 normal loop, low nibble transparent colour ; only the transparent colour is read, then the RLE lines : colour in the high nibble, length in the low nibble, 0 at the end of each line) is at address Parameters:0,1 of 6502 RAM, its left side at X Parameter:2, its bottom line at Y Parameter:3 (AGI pixels), with the object priority Parameter:4 ; bit 0 of Parameter:5 mirrors it horizontally. The plane top is at screen line Parameters:6,7. A pixel is drawn when it is not transparent and the object priority is greater than or equal to the plane priority at that point ; on a control line (priority 0 to 3) the first point below which is not one is used, 15 if the bottom is reached (assumptions, see Neo6502AGI docs/specs/view-v2.md). The cel is clipped to the plane ; a line longer than the width is cut. Draw Cel never writes the plane. The caller handles the order of the objects : after Restore Rect has erased an object, the objects it overlapped must be drawn again. Errors : 1 empty cel, position outside the plane, header outside 6502 RAM or unsupported mode ; 2 cel data cut by the end of 6502 RAM.
C (llvm-mos)
/* Dessiner un cel sur l'image (groupe 39, 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)
;
}
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
/* image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50) */
static const uint8_t img[] = {0xF0, 0x0C, 0xF2, 0x09, 0xF6, 0x14, 0x1E, 0x64, 0x1E, 0x64, 0x50, 0x14, 0x50, 0x14, 0x1E, 0xF0, 0x0E, 0xF8, 0x32, 0x32, 0xFF};
/* cel 4 x 2, transparent = 0 : ligne du haut 0,3,3,1 ; ligne du bas 2,2,2,2 (RLE : couleur dans le quartet haut, longueur dans le bas, 0 en fin de ligne) */
static const uint8_t cel[] = {0x04, 0x02, 0x00, 0x01, 0x32, 0x11, 0x00, 0x24, 0x00};
int main(void) {
uint8_t e0, a1, a2, a3, a4, e1, a5, c1, p1;
putchar(12); /* efface l'écran avant toute mesure */
libre();
p16(0, (uint16_t)img);
p16(2, sizeof img);
ControlPort.params[4] = 1;
api(39, 1);
libre();
p16(0, 72);
api(39, 2);
libre();
p16(0, (uint16_t)cel);
ControlPort.params[2] = 60;
ControlPort.params[3] = 60;
ControlPort.params[4] = 12;
ControlPort.params[5] = 0;
p16(6, 72);
api(39, 5);
e0 = ControlPort.error;
libre(); p16(0, 120); p16(2, 131); api(5, 33); a1 = ControlPort.params[0]; /* 5,33 : Read Pixel */
libre(); p16(0, 122); p16(2, 131); api(5, 33); a2 = ControlPort.params[0]; /* 5,33 : Read Pixel */
libre(); p16(0, 126); p16(2, 131); api(5, 33); a3 = ControlPort.params[0]; /* 5,33 : Read Pixel */
libre(); p16(0, 120); p16(2, 132); api(5, 33); a4 = ControlPort.params[0]; /* 5,33 : Read Pixel */
libre();
p16(0, (uint16_t)cel);
ControlPort.params[2] = 60;
ControlPort.params[3] = 76;
ControlPort.params[4] = 5;
ControlPort.params[5] = 0;
p16(6, 72);
api(39, 5);
e1 = ControlPort.error;
libre(); p16(0, 120); p16(2, 148); api(5, 33); a5 = ControlPort.params[0]; /* 5,33 : Read Pixel */
libre();
ControlPort.params[0] = 60;
ControlPort.params[1] = 60;
api(39, 4);
c1 = ControlPort.params[2];
p1 = ControlPort.params[3];
printf("Priorite 12 : erreur %u\n", e0);
printf("Haut : %u %u %u, bas : %u\n", a1, a2, a3, a4);
printf("Priorite 5 : erreur %u, ecran %u\n", e1, a5);
printf("Plan : couleur %u, priorite %u\n", c1, p1);
return 0;
}Priorite 12 : erreur 0
Haut : 14 3 1, bas : 2
Priorite 5 : erreur 0, ecran 14
Plan : couleur 14, priorite 9Mad Pascal
// Dessiner un cel sur l'image (groupe 39, fonction 5, Trinity).
program agi5;
uses crt, neo6502;
// image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
const img: array[0..20] of byte = ($F0, $0C, $F2, $09, $F6, $14, $1E, $64, $1E, $64, $50, $14, $50, $14, $1E, $F0, $0E, $F8, $32, $32, $FF);
// cel 4 x 2, transparent = 0 : ligne du haut 0,3,3,1 ; ligne du bas 2,2,2,2 (RLE : couleur dans le quartet haut, longueur dans le bas, 0 en fin de ligne)
const cel: array[0..8] of byte = ($04, $02, $00, $01, $32, $11, $00, $24, $00);
var e0, a1, a2, a3, a4, e1, a5, c1, p1: byte;
procedure p16(i: byte; v: word); // paramètre 16 bits en Pi, Pi+1
begin
NeoMessage.params[i] := lo(v);
NeoMessage.params[i + 1] := hi(v);
end;
procedure appel(g, f: byte); // lance l'appel et attend la fin
begin
NeoSendMessage(g, f);
NeoWaitMessage;
end;
begin
write(chr(12)); // efface l'écran avant toute mesure
NeoWaitMessage;
p16(0, word(@img));
p16(2, 21);
NeoMessage.params[4] := 1;
appel(39, 1);
NeoWaitMessage;
p16(0, 72);
appel(39, 2);
NeoWaitMessage;
p16(0, word(@cel));
NeoMessage.params[2] := 60;
NeoMessage.params[3] := 60;
NeoMessage.params[4] := 12;
NeoMessage.params[5] := 0;
p16(6, 72);
appel(39, 5);
e0 := NeoMessage.error;
NeoWaitMessage; p16(0, 120); p16(2, 131); appel(5, 33); a1 := NeoMessage.params[0]; // 5,33 : Read Pixel
NeoWaitMessage; p16(0, 122); p16(2, 131); appel(5, 33); a2 := NeoMessage.params[0]; // 5,33 : Read Pixel
NeoWaitMessage; p16(0, 126); p16(2, 131); appel(5, 33); a3 := NeoMessage.params[0]; // 5,33 : Read Pixel
NeoWaitMessage; p16(0, 120); p16(2, 132); appel(5, 33); a4 := NeoMessage.params[0]; // 5,33 : Read Pixel
NeoWaitMessage;
p16(0, word(@cel));
NeoMessage.params[2] := 60;
NeoMessage.params[3] := 76;
NeoMessage.params[4] := 5;
NeoMessage.params[5] := 0;
p16(6, 72);
appel(39, 5);
e1 := NeoMessage.error;
NeoWaitMessage; p16(0, 120); p16(2, 148); appel(5, 33); a5 := NeoMessage.params[0]; // 5,33 : Read Pixel
NeoWaitMessage;
NeoMessage.params[0] := 60;
NeoMessage.params[1] := 60;
appel(39, 4);
c1 := NeoMessage.params[2];
p1 := NeoMessage.params[3];
writeln('Priorite 12 : erreur ', e0);
writeln('Haut : ', a1, ' ', a2, ' ', a3, ', bas : ', a4);
writeln('Priorite 5 : erreur ', e1, ', ecran ', a5);
writeln('Plan : couleur ', c1, ', priorite ', p1);
end.Priorite 12 : erreur 0
Haut : 14 3 1, bas : 2
Priorite 5 : erreur 0, ecran 14
Plan : couleur 14, priorite 9NeoBASIC
10 ' Dessiner un cel sur l'image (groupe 39, fonction 5, Trinity)
20 ' image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
30 di = alloc(21)
40 poke di + 0, 240 : poke di + 1, 12 : poke di + 2, 242 : poke di + 3, 9 : poke di + 4, 246 : poke di + 5, 20
50 poke di + 6, 30 : poke di + 7, 100 : poke di + 8, 30 : poke di + 9, 100 : poke di + 10, 80 : poke di + 11, 20
60 poke di + 12, 80 : poke di + 13, 20 : poke di + 14, 30 : poke di + 15, 240 : poke di + 16, 14 : poke di + 17, 248
70 poke di + 18, 50 : poke di + 19, 50 : poke di + 20, 255
80 ' cel 4 x 2, transparent = 0 : ligne du haut 0,3,3,1 ; ligne du bas 2,2,2,2 (RLE : couleur dans le quartet haut, longueur dans le bas, 0 en fin de ligne)
90 dc = alloc(9)
100 poke dc + 0, 4 : poke dc + 1, 2 : poke dc + 2, 0 : poke dc + 3, 1 : poke dc + 4, 50 : poke dc + 5, 17
110 poke dc + 6, 0 : poke dc + 7, 36 : poke dc + 8, 0
120 cls
130 while peek($ff00) : wend : doke $ff04 + 0, di : doke $ff04 + 2, 21 : poke $ff04 + 4, 1 : f = 1 : gosub 8100
140 while peek($ff00) : wend : doke $ff04 + 0, 72 : f = 2 : gosub 8100
150 while peek($ff00) : wend : doke $ff04 + 0, dc : poke $ff04 + 2, 60 : poke $ff04 + 3, 60 : poke $ff04 + 4, 12 : poke $ff04 + 5, 0 : doke $ff04 + 6, 72 : f = 5 : gosub 8100
160 e0 = e
170 while peek($ff00) : wend : doke $ff04, 120 : doke $ff06, 131 : f = 33 : g = 5 : gosub 8110 : a1 = peek($ff04)
180 while peek($ff00) : wend : doke $ff04, 122 : doke $ff06, 131 : f = 33 : g = 5 : gosub 8110 : a2 = peek($ff04)
190 while peek($ff00) : wend : doke $ff04, 126 : doke $ff06, 131 : f = 33 : g = 5 : gosub 8110 : a3 = peek($ff04)
200 while peek($ff00) : wend : doke $ff04, 120 : doke $ff06, 132 : f = 33 : g = 5 : gosub 8110 : a4 = peek($ff04)
210 while peek($ff00) : wend : doke $ff04 + 0, dc : poke $ff04 + 2, 60 : poke $ff04 + 3, 76 : poke $ff04 + 4, 5 : poke $ff04 + 5, 0 : doke $ff04 + 6, 72 : f = 5 : gosub 8100
220 e1 = e
230 while peek($ff00) : wend : doke $ff04, 120 : doke $ff06, 148 : f = 33 : g = 5 : gosub 8110 : a5 = peek($ff04)
240 while peek($ff00) : wend : poke $ff04 + 0, 60 : poke $ff04 + 1, 60 : f = 4 : gosub 8100
250 c1 = peek($ff04 + 2)
260 p1 = peek($ff04 + 3)
270 print "Priorite 12 : erreur ";e0
280 print "Haut : ";a1;" ";a2;" ";a3;", bas : ";a4
290 print "Priorite 5 : erreur ";e1;", ecran ";a5
300 print "Plan : couleur ";c1;", priorite ";p1
310 end
8100 ' appel 39,f, parametres deja poses ; erreur dans e
8105 g = 39
8110 poke $ff01, f : poke $ff00, g
8120 while peek($ff00) : wend : e = peek($ff02) : returnPriorite 12 : erreur 0
Haut : 14 3 1, bas : 2
Priorite 5 : erreur 0, ecran 14
Plan : couleur 14, priorite 9Assembleur 65C02 (64tass)
; Dessiner un cel sur l'image (groupe 39, 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 ; efface l'écran avant toute mesure
jsr WriteCharacter
jsr WaitMessage
lda #<img
sta ControlPort+4
lda #>img
sta ControlPort+5
lda #<(fimg-img)
sta ControlPort+6
lda #>(fimg-img)
sta ControlPort+7
lda #1
sta ControlPort+8
lda #39
ldx #1
jsr appel
jsr WaitMessage
lda #<72
sta ControlPort+4
lda #>72
sta ControlPort+5
lda #39
ldx #2
jsr appel
jsr WaitMessage
lda #<cel
sta ControlPort+4
lda #>cel
sta ControlPort+5
lda #60
sta ControlPort+6
lda #60
sta ControlPort+7
lda #12
sta ControlPort+8
stz ControlPort+9
lda #<72
sta ControlPort+10
lda #>72
sta ControlPort+11
lda #39
ldx #5
jsr appel
lda ControlPort+2
sta e0
jsr WaitMessage
lda #<120
sta ControlPort+4
lda #>120
sta ControlPort+5
lda #<131
sta ControlPort+6
lda #>131
sta ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
sta a1
jsr WaitMessage
lda #<122
sta ControlPort+4
lda #>122
sta ControlPort+5
lda #<131
sta ControlPort+6
lda #>131
sta ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
sta a2
jsr WaitMessage
lda #<126
sta ControlPort+4
lda #>126
sta ControlPort+5
lda #<131
sta ControlPort+6
lda #>131
sta ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
sta a3
jsr WaitMessage
lda #<120
sta ControlPort+4
lda #>120
sta ControlPort+5
lda #<132
sta ControlPort+6
lda #>132
sta ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
sta a4
jsr WaitMessage
lda #<cel
sta ControlPort+4
lda #>cel
sta ControlPort+5
lda #60
sta ControlPort+6
lda #76
sta ControlPort+7
lda #5
sta ControlPort+8
stz ControlPort+9
lda #<72
sta ControlPort+10
lda #>72
sta ControlPort+11
lda #39
ldx #5
jsr appel
lda ControlPort+2
sta e1
jsr WaitMessage
lda #<120
sta ControlPort+4
lda #>120
sta ControlPort+5
lda #<148
sta ControlPort+6
lda #>148
sta ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
sta a5
jsr WaitMessage
lda #60
sta ControlPort+4
lda #60
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c1
lda ControlPort+7
sta p1
lda #<t0
ldx #>t0
jsr ecrire
lda e0
jsr decimal
lda #13
jsr WriteCharacter
lda #<t1
ldx #>t1
jsr ecrire
lda a1
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda a2
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda a3
jsr decimal
lda #<t3
ldx #>t3
jsr ecrire
lda a4
jsr decimal
lda #13
jsr WriteCharacter
lda #<t4
ldx #>t4
jsr ecrire
lda e1
jsr decimal
lda #<t5
ldx #>t5
jsr ecrire
lda a5
jsr decimal
lda #13
jsr WriteCharacter
lda #<t6
ldx #>t6
jsr ecrire
lda c1
jsr decimal
lda #<t7
ldx #>t7
jsr ecrire
lda p1
jsr decimal
lda #13
jsr WriteCharacter
rts
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
; image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
img:
.byte $F0, $0C, $F2, $09, $F6, $14, $1E, $64
.byte $1E, $64, $50, $14, $50, $14, $1E, $F0
.byte $0E, $F8, $32, $32, $FF
fimg:
; cel 4 x 2, transparent = 0 : ligne du haut 0,3,3,1 ; ligne du bas 2,2,2,2 (RLE : couleur dans le quartet haut, longueur dans le bas, 0 en fin de ligne)
cel:
.byte $04, $02, $00, $01, $32, $11, $00, $24
.byte $00
fcel:
e0: .byte 0
a1: .byte 0
a2: .byte 0
a3: .byte 0
a4: .byte 0
e1: .byte 0
a5: .byte 0
c1: .byte 0
p1: .byte 0
t0: .text "Priorite 12 : erreur ", 0
t1: .text "Haut : ", 0
t2: .text " ", 0
t3: .text ", bas : ", 0
t4: .text "Priorite 5 : erreur ", 0
t5: .text ", ecran ", 0
t6: .text "Plan : couleur ", 0
t7: .text ", priorite ", 0Priorite 12 : erreur 0
Haut : 14 3 1, bas : 2
Priorite 5 : erreur 0, ecran 14
Plan : couleur 14, priorite 939,6 Restore Rect Trinity
Recopie à l'écran un rectangle du plan AGI : efface les objets qui y étaient dessinés.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | X |
P1 | uint8 | Y |
P2 | uint8 | largeur |
P3 | uint8 | hauteur |
P4-P5 | uint16 | ligne de l'écran où est le haut du plan |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | 1 si la largeur ou la hauteur est 0, ou si le mode n'est pas géré |
Le rectangle est coupé aux bords du plan. Les objets qui le recouvraient doivent ensuite être redessinés par l'appelant. L'exemple dessine un cel, restaure 2 × 1 points : le point restauré retrouve la couleur du plan (14), le voisin du cel est inchangé. NeoBASIC n'a pas de mot-clé pour cet appel : l'exemple écrit la boîte aux lettres.
Texte de la documentation du firmware (anglais)
Trinity (T-109). Copies the visual colours of the AGI plane to the screen on the rectangle X Parameter:0, Y Parameter:1, width Parameter:2, height Parameter:3 (AGI pixels, clipped to the plane), the plane top being at screen line Parameters:4,5 : this erases the objects drawn there. Error 1 if the width or the height is 0 or the mode is not supported.
C (llvm-mos)
/* Restaurer un rectangle de l'image (groupe 39, 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)
;
}
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
/* image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50) */
static const uint8_t img[] = {0xF0, 0x0C, 0xF2, 0x09, 0xF6, 0x14, 0x1E, 0x64, 0x1E, 0x64, 0x50, 0x14, 0x50, 0x14, 0x1E, 0xF0, 0x0E, 0xF8, 0x32, 0x32, 0xFF};
/* cel 4 x 2, transparent = 0 : ligne du haut 0,3,3,1 ; ligne du bas 2,2,2,2 (RLE : couleur dans le quartet haut, longueur dans le bas, 0 en fin de ligne) */
static const uint8_t cel[] = {0x04, 0x02, 0x00, 0x01, 0x32, 0x11, 0x00, 0x24, 0x00};
int main(void) {
uint8_t a1, a2, e0, a3, a4, e1;
putchar(12); /* efface l'écran avant toute mesure */
libre();
p16(0, (uint16_t)img);
p16(2, sizeof img);
ControlPort.params[4] = 1;
api(39, 1);
libre();
p16(0, 72);
api(39, 2);
libre();
p16(0, (uint16_t)cel);
ControlPort.params[2] = 60;
ControlPort.params[3] = 60;
ControlPort.params[4] = 12;
ControlPort.params[5] = 0;
p16(6, 72);
api(39, 5);
libre(); p16(0, 122); p16(2, 131); api(5, 33); a1 = ControlPort.params[0]; /* 5,33 : Read Pixel */
libre(); p16(0, 126); p16(2, 131); api(5, 33); a2 = ControlPort.params[0]; /* 5,33 : Read Pixel */
libre();
ControlPort.params[0] = 60;
ControlPort.params[1] = 59;
ControlPort.params[2] = 2;
ControlPort.params[3] = 1;
p16(4, 72);
api(39, 6);
e0 = ControlPort.error;
libre(); p16(0, 122); p16(2, 131); api(5, 33); a3 = ControlPort.params[0]; /* 5,33 : Read Pixel */
libre(); p16(0, 126); p16(2, 131); api(5, 33); a4 = ControlPort.params[0]; /* 5,33 : Read Pixel */
libre();
ControlPort.params[0] = 60;
ControlPort.params[1] = 59;
ControlPort.params[2] = 0;
ControlPort.params[3] = 1;
p16(4, 72);
api(39, 6);
e1 = ControlPort.error;
printf("Avant : %u et %u\n", a1, a2);
printf("Restaurer : erreur %u, apres : %u et %u\n", e0, a3, a4);
printf("Largeur 0 : erreur %u\n", e1);
return 0;
}Avant : 3 et 1
Restaurer : erreur 0, apres : 14 et 1
Largeur 0 : erreur 1Mad Pascal
// Restaurer un rectangle de l'image (groupe 39, fonction 6, Trinity).
program agi6;
uses crt, neo6502;
// image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
const img: array[0..20] of byte = ($F0, $0C, $F2, $09, $F6, $14, $1E, $64, $1E, $64, $50, $14, $50, $14, $1E, $F0, $0E, $F8, $32, $32, $FF);
// cel 4 x 2, transparent = 0 : ligne du haut 0,3,3,1 ; ligne du bas 2,2,2,2 (RLE : couleur dans le quartet haut, longueur dans le bas, 0 en fin de ligne)
const cel: array[0..8] of byte = ($04, $02, $00, $01, $32, $11, $00, $24, $00);
var a1, a2, e0, a3, a4, e1: byte;
procedure p16(i: byte; v: word); // paramètre 16 bits en Pi, Pi+1
begin
NeoMessage.params[i] := lo(v);
NeoMessage.params[i + 1] := hi(v);
end;
procedure appel(g, f: byte); // lance l'appel et attend la fin
begin
NeoSendMessage(g, f);
NeoWaitMessage;
end;
begin
write(chr(12)); // efface l'écran avant toute mesure
NeoWaitMessage;
p16(0, word(@img));
p16(2, 21);
NeoMessage.params[4] := 1;
appel(39, 1);
NeoWaitMessage;
p16(0, 72);
appel(39, 2);
NeoWaitMessage;
p16(0, word(@cel));
NeoMessage.params[2] := 60;
NeoMessage.params[3] := 60;
NeoMessage.params[4] := 12;
NeoMessage.params[5] := 0;
p16(6, 72);
appel(39, 5);
NeoWaitMessage; p16(0, 122); p16(2, 131); appel(5, 33); a1 := NeoMessage.params[0]; // 5,33 : Read Pixel
NeoWaitMessage; p16(0, 126); p16(2, 131); appel(5, 33); a2 := NeoMessage.params[0]; // 5,33 : Read Pixel
NeoWaitMessage;
NeoMessage.params[0] := 60;
NeoMessage.params[1] := 59;
NeoMessage.params[2] := 2;
NeoMessage.params[3] := 1;
p16(4, 72);
appel(39, 6);
e0 := NeoMessage.error;
NeoWaitMessage; p16(0, 122); p16(2, 131); appel(5, 33); a3 := NeoMessage.params[0]; // 5,33 : Read Pixel
NeoWaitMessage; p16(0, 126); p16(2, 131); appel(5, 33); a4 := NeoMessage.params[0]; // 5,33 : Read Pixel
NeoWaitMessage;
NeoMessage.params[0] := 60;
NeoMessage.params[1] := 59;
NeoMessage.params[2] := 0;
NeoMessage.params[3] := 1;
p16(4, 72);
appel(39, 6);
e1 := NeoMessage.error;
writeln('Avant : ', a1, ' et ', a2);
writeln('Restaurer : erreur ', e0, ', apres : ', a3, ' et ', a4);
writeln('Largeur 0 : erreur ', e1);
end.Avant : 3 et 1
Restaurer : erreur 0, apres : 14 et 1
Largeur 0 : erreur 1NeoBASIC
10 ' Restaurer un rectangle de l'image (groupe 39, fonction 6, Trinity)
20 ' image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
30 di = alloc(21)
40 poke di + 0, 240 : poke di + 1, 12 : poke di + 2, 242 : poke di + 3, 9 : poke di + 4, 246 : poke di + 5, 20
50 poke di + 6, 30 : poke di + 7, 100 : poke di + 8, 30 : poke di + 9, 100 : poke di + 10, 80 : poke di + 11, 20
60 poke di + 12, 80 : poke di + 13, 20 : poke di + 14, 30 : poke di + 15, 240 : poke di + 16, 14 : poke di + 17, 248
70 poke di + 18, 50 : poke di + 19, 50 : poke di + 20, 255
80 ' cel 4 x 2, transparent = 0 : ligne du haut 0,3,3,1 ; ligne du bas 2,2,2,2 (RLE : couleur dans le quartet haut, longueur dans le bas, 0 en fin de ligne)
90 dc = alloc(9)
100 poke dc + 0, 4 : poke dc + 1, 2 : poke dc + 2, 0 : poke dc + 3, 1 : poke dc + 4, 50 : poke dc + 5, 17
110 poke dc + 6, 0 : poke dc + 7, 36 : poke dc + 8, 0
120 cls
130 while peek($ff00) : wend : doke $ff04 + 0, di : doke $ff04 + 2, 21 : poke $ff04 + 4, 1 : f = 1 : gosub 8100
140 while peek($ff00) : wend : doke $ff04 + 0, 72 : f = 2 : gosub 8100
150 while peek($ff00) : wend : doke $ff04 + 0, dc : poke $ff04 + 2, 60 : poke $ff04 + 3, 60 : poke $ff04 + 4, 12 : poke $ff04 + 5, 0 : doke $ff04 + 6, 72 : f = 5 : gosub 8100
160 while peek($ff00) : wend : doke $ff04, 122 : doke $ff06, 131 : f = 33 : g = 5 : gosub 8110 : a1 = peek($ff04)
170 while peek($ff00) : wend : doke $ff04, 126 : doke $ff06, 131 : f = 33 : g = 5 : gosub 8110 : a2 = peek($ff04)
180 while peek($ff00) : wend : poke $ff04 + 0, 60 : poke $ff04 + 1, 59 : poke $ff04 + 2, 2 : poke $ff04 + 3, 1 : doke $ff04 + 4, 72 : f = 6 : gosub 8100
190 e0 = e
200 while peek($ff00) : wend : doke $ff04, 122 : doke $ff06, 131 : f = 33 : g = 5 : gosub 8110 : a3 = peek($ff04)
210 while peek($ff00) : wend : doke $ff04, 126 : doke $ff06, 131 : f = 33 : g = 5 : gosub 8110 : a4 = peek($ff04)
220 while peek($ff00) : wend : poke $ff04 + 0, 60 : poke $ff04 + 1, 59 : poke $ff04 + 2, 0 : poke $ff04 + 3, 1 : doke $ff04 + 4, 72 : f = 6 : gosub 8100
230 e1 = e
240 print "Avant : ";a1;" et ";a2
250 print "Restaurer : erreur ";e0;", apres : ";a3;" et ";a4
260 print "Largeur 0 : erreur ";e1
270 end
8100 ' appel 39,f, parametres deja poses ; erreur dans e
8105 g = 39
8110 poke $ff01, f : poke $ff00, g
8120 while peek($ff00) : wend : e = peek($ff02) : returnAvant : 3 et 1
Restaurer : erreur 0, apres : 14 et 1
Largeur 0 : erreur 1Assembleur 65C02 (64tass)
; Restaurer un rectangle de l'image (groupe 39, 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 ; efface l'écran avant toute mesure
jsr WriteCharacter
jsr WaitMessage
lda #<img
sta ControlPort+4
lda #>img
sta ControlPort+5
lda #<(fimg-img)
sta ControlPort+6
lda #>(fimg-img)
sta ControlPort+7
lda #1
sta ControlPort+8
lda #39
ldx #1
jsr appel
jsr WaitMessage
lda #<72
sta ControlPort+4
lda #>72
sta ControlPort+5
lda #39
ldx #2
jsr appel
jsr WaitMessage
lda #<cel
sta ControlPort+4
lda #>cel
sta ControlPort+5
lda #60
sta ControlPort+6
lda #60
sta ControlPort+7
lda #12
sta ControlPort+8
stz ControlPort+9
lda #<72
sta ControlPort+10
lda #>72
sta ControlPort+11
lda #39
ldx #5
jsr appel
jsr WaitMessage
lda #<122
sta ControlPort+4
lda #>122
sta ControlPort+5
lda #<131
sta ControlPort+6
lda #>131
sta ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
sta a1
jsr WaitMessage
lda #<126
sta ControlPort+4
lda #>126
sta ControlPort+5
lda #<131
sta ControlPort+6
lda #>131
sta ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
sta a2
jsr WaitMessage
lda #60
sta ControlPort+4
lda #59
sta ControlPort+5
lda #2
sta ControlPort+6
lda #1
sta ControlPort+7
lda #<72
sta ControlPort+8
lda #>72
sta ControlPort+9
lda #39
ldx #6
jsr appel
lda ControlPort+2
sta e0
jsr WaitMessage
lda #<122
sta ControlPort+4
lda #>122
sta ControlPort+5
lda #<131
sta ControlPort+6
lda #>131
sta ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
sta a3
jsr WaitMessage
lda #<126
sta ControlPort+4
lda #>126
sta ControlPort+5
lda #<131
sta ControlPort+6
lda #>131
sta ControlPort+7
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
sta a4
jsr WaitMessage
lda #60
sta ControlPort+4
lda #59
sta ControlPort+5
stz ControlPort+6
lda #1
sta ControlPort+7
lda #<72
sta ControlPort+8
lda #>72
sta ControlPort+9
lda #39
ldx #6
jsr appel
lda ControlPort+2
sta e1
lda #<t0
ldx #>t0
jsr ecrire
lda a1
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
lda a2
jsr decimal
lda #13
jsr WriteCharacter
lda #<t2
ldx #>t2
jsr ecrire
lda e0
jsr decimal
lda #<t3
ldx #>t3
jsr ecrire
lda a3
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
lda a4
jsr decimal
lda #13
jsr WriteCharacter
lda #<t4
ldx #>t4
jsr ecrire
lda e1
jsr decimal
lda #13
jsr WriteCharacter
rts
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
; image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
img:
.byte $F0, $0C, $F2, $09, $F6, $14, $1E, $64
.byte $1E, $64, $50, $14, $50, $14, $1E, $F0
.byte $0E, $F8, $32, $32, $FF
fimg:
; cel 4 x 2, transparent = 0 : ligne du haut 0,3,3,1 ; ligne du bas 2,2,2,2 (RLE : couleur dans le quartet haut, longueur dans le bas, 0 en fin de ligne)
cel:
.byte $04, $02, $00, $01, $32, $11, $00, $24
.byte $00
fcel:
a1: .byte 0
a2: .byte 0
e0: .byte 0
a3: .byte 0
a4: .byte 0
e1: .byte 0
t0: .text "Avant : ", 0
t1: .text " et ", 0
t2: .text "Restaurer : erreur ", 0
t3: .text ", apres : ", 0
t4: .text "Largeur 0 : erreur ", 0Avant : 3 et 1
Restaurer : erreur 0, apres : 14 et 1
Largeur 0 : erreur 139,7 Add Cel To Plane Trinity
Écrit un cel dans le plan AGI (commande add.to.pic) au lieu de l'écran.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse de l'en-tête du cel dans la RAM du 6502 |
P2 | uint8 | X du côté gauche |
P3 | uint8 | Y de la ligne du bas |
P4 | uint8 | priorité (4 à 15) |
P5 | uint8 | bit 0 : retourner horizontalement |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | 1 priorité hors de 4 à 15, cel vide, position hors du plan ou en-tête hors de la RAM ; 2 données du cel coupées |
Mêmes paramètres que 39,5, sans ligne d'écran : chaque point non transparent qui passe le test de priorité reçoit la couleur du cel et la priorité donnée (les lignes de contrôle 0 à 3 déjà dans le plan sont gardées). La priorité 0 (« selon Y ») est à calculer par l'appelant, d'où le refus de 0 à 3. 39,6 montre ensuite le résultat. L'exemple lit le plan après l'ajout, essaie la priorité 3 (erreur 1), puis la priorité 5 sur un plan de priorité 9 : rien n'est écrit. NeoBASIC n'a pas de mot-clé pour cet appel : l'exemple écrit la boîte aux lettres.
Texte de la documentation du firmware (anglais)
Trinity (T-122), for the AGI command add.to.pic. Same parameters as Draw Cel (cel header at Parameters:0,1 of 6502 RAM, left X Parameter:2, bottom Y Parameter:3, priority Parameter:4, bit 0 of Parameter:5 = mirror) without screen line : the cel is written into the AGI plane, not to the screen. Each point which is not transparent and passes the priority test of Draw Cel (priority greater than or equal to the plane priority, control lines included) receives the cel colour and the given priority. The priority must be 4 to 15 (0, "from Y", is computed by the caller). Same clipping as Draw Cel ; Restore Rect then shows the result. Errors : 1 priority outside 4-15 and the errors 1 and 2 of Draw Cel (the screen mode is not used).
C (llvm-mos)
/* Ajouter un cel au plan AGI (groupe 39, 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)
;
}
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
/* image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50) */
static const uint8_t img[] = {0xF0, 0x0C, 0xF2, 0x09, 0xF6, 0x14, 0x1E, 0x64, 0x1E, 0x64, 0x50, 0x14, 0x50, 0x14, 0x1E, 0xF0, 0x0E, 0xF8, 0x32, 0x32, 0xFF};
/* cel 4 x 2, transparent = 0 : ligne du haut 0,3,3,1 ; ligne du bas 2,2,2,2 (RLE : couleur dans le quartet haut, longueur dans le bas, 0 en fin de ligne) */
static const uint8_t cel[] = {0x04, 0x02, 0x00, 0x01, 0x32, 0x11, 0x00, 0x24, 0x00};
int main(void) {
uint8_t e0, c1, p1, c2, p2, c3, p3, e1, e2, c4, p4;
libre();
p16(0, (uint16_t)img);
p16(2, sizeof img);
ControlPort.params[4] = 1;
api(39, 1);
libre();
p16(0, (uint16_t)cel);
ControlPort.params[2] = 60;
ControlPort.params[3] = 60;
ControlPort.params[4] = 12;
ControlPort.params[5] = 0;
api(39, 7);
e0 = ControlPort.error;
libre();
ControlPort.params[0] = 61;
ControlPort.params[1] = 59;
api(39, 4);
c1 = ControlPort.params[2];
p1 = ControlPort.params[3];
libre();
ControlPort.params[0] = 60;
ControlPort.params[1] = 59;
api(39, 4);
c2 = ControlPort.params[2];
p2 = ControlPort.params[3];
libre();
ControlPort.params[0] = 60;
ControlPort.params[1] = 60;
api(39, 4);
c3 = ControlPort.params[2];
p3 = ControlPort.params[3];
libre();
p16(0, (uint16_t)cel);
ControlPort.params[2] = 60;
ControlPort.params[3] = 60;
ControlPort.params[4] = 3;
ControlPort.params[5] = 0;
api(39, 7);
e1 = ControlPort.error;
libre();
p16(0, (uint16_t)cel);
ControlPort.params[2] = 60;
ControlPort.params[3] = 76;
ControlPort.params[4] = 5;
ControlPort.params[5] = 0;
api(39, 7);
e2 = ControlPort.error;
libre();
ControlPort.params[0] = 60;
ControlPort.params[1] = 76;
api(39, 4);
c4 = ControlPort.params[2];
p4 = ControlPort.params[3];
printf("Ajout : erreur %u\n", e0);
printf("Cel (61, 59) : couleur %u, priorite %u\n", c1, p1);
printf("Vide (60, 59) : couleur %u, priorite %u\n", c2, p2);
printf("Bas (60, 60) : couleur %u, priorite %u\n", c3, p3);
printf("Priorite 3 : erreur %u\n", e1);
printf("Priorite 5 : erreur %u\n", e2);
printf("Point (60, 76) : couleur %u, priorite %u\n", c4, p4);
return 0;
}Ajout : erreur 0
Cel (61, 59) : couleur 3, priorite 12
Vide (60, 59) : couleur 14, priorite 9
Bas (60, 60) : couleur 2, priorite 12
Priorite 3 : erreur 1
Priorite 5 : erreur 0
Point (60, 76) : couleur 14, priorite 9Mad Pascal
// Ajouter un cel au plan AGI (groupe 39, fonction 7, Trinity).
program agi7;
uses crt, neo6502;
// image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
const img: array[0..20] of byte = ($F0, $0C, $F2, $09, $F6, $14, $1E, $64, $1E, $64, $50, $14, $50, $14, $1E, $F0, $0E, $F8, $32, $32, $FF);
// cel 4 x 2, transparent = 0 : ligne du haut 0,3,3,1 ; ligne du bas 2,2,2,2 (RLE : couleur dans le quartet haut, longueur dans le bas, 0 en fin de ligne)
const cel: array[0..8] of byte = ($04, $02, $00, $01, $32, $11, $00, $24, $00);
var e0, c1, p1, c2, p2, c3, p3, e1, e2, c4, p4: byte;
procedure p16(i: byte; v: word); // paramètre 16 bits en Pi, Pi+1
begin
NeoMessage.params[i] := lo(v);
NeoMessage.params[i + 1] := hi(v);
end;
procedure appel(g, f: byte); // lance l'appel et attend la fin
begin
NeoSendMessage(g, f);
NeoWaitMessage;
end;
begin
NeoWaitMessage;
p16(0, word(@img));
p16(2, 21);
NeoMessage.params[4] := 1;
appel(39, 1);
NeoWaitMessage;
p16(0, word(@cel));
NeoMessage.params[2] := 60;
NeoMessage.params[3] := 60;
NeoMessage.params[4] := 12;
NeoMessage.params[5] := 0;
appel(39, 7);
e0 := NeoMessage.error;
NeoWaitMessage;
NeoMessage.params[0] := 61;
NeoMessage.params[1] := 59;
appel(39, 4);
c1 := NeoMessage.params[2];
p1 := NeoMessage.params[3];
NeoWaitMessage;
NeoMessage.params[0] := 60;
NeoMessage.params[1] := 59;
appel(39, 4);
c2 := NeoMessage.params[2];
p2 := NeoMessage.params[3];
NeoWaitMessage;
NeoMessage.params[0] := 60;
NeoMessage.params[1] := 60;
appel(39, 4);
c3 := NeoMessage.params[2];
p3 := NeoMessage.params[3];
NeoWaitMessage;
p16(0, word(@cel));
NeoMessage.params[2] := 60;
NeoMessage.params[3] := 60;
NeoMessage.params[4] := 3;
NeoMessage.params[5] := 0;
appel(39, 7);
e1 := NeoMessage.error;
NeoWaitMessage;
p16(0, word(@cel));
NeoMessage.params[2] := 60;
NeoMessage.params[3] := 76;
NeoMessage.params[4] := 5;
NeoMessage.params[5] := 0;
appel(39, 7);
e2 := NeoMessage.error;
NeoWaitMessage;
NeoMessage.params[0] := 60;
NeoMessage.params[1] := 76;
appel(39, 4);
c4 := NeoMessage.params[2];
p4 := NeoMessage.params[3];
writeln('Ajout : erreur ', e0);
writeln('Cel (61, 59) : couleur ', c1, ', priorite ', p1);
writeln('Vide (60, 59) : couleur ', c2, ', priorite ', p2);
writeln('Bas (60, 60) : couleur ', c3, ', priorite ', p3);
writeln('Priorite 3 : erreur ', e1);
writeln('Priorite 5 : erreur ', e2);
writeln('Point (60, 76) : couleur ', c4, ', priorite ', p4);
end.Ajout : erreur 0
Cel (61, 59) : couleur 3, priorite 12
Vide (60, 59) : couleur 14, priorite 9
Bas (60, 60) : couleur 2, priorite 12
Priorite 3 : erreur 1
Priorite 5 : erreur 0
Point (60, 76) : couleur 14, priorite 9NeoBASIC
10 ' Ajouter un cel au plan AGI (groupe 39, fonction 7, Trinity)
20 ' image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
30 di = alloc(21)
40 poke di + 0, 240 : poke di + 1, 12 : poke di + 2, 242 : poke di + 3, 9 : poke di + 4, 246 : poke di + 5, 20
50 poke di + 6, 30 : poke di + 7, 100 : poke di + 8, 30 : poke di + 9, 100 : poke di + 10, 80 : poke di + 11, 20
60 poke di + 12, 80 : poke di + 13, 20 : poke di + 14, 30 : poke di + 15, 240 : poke di + 16, 14 : poke di + 17, 248
70 poke di + 18, 50 : poke di + 19, 50 : poke di + 20, 255
80 ' cel 4 x 2, transparent = 0 : ligne du haut 0,3,3,1 ; ligne du bas 2,2,2,2 (RLE : couleur dans le quartet haut, longueur dans le bas, 0 en fin de ligne)
90 dc = alloc(9)
100 poke dc + 0, 4 : poke dc + 1, 2 : poke dc + 2, 0 : poke dc + 3, 1 : poke dc + 4, 50 : poke dc + 5, 17
110 poke dc + 6, 0 : poke dc + 7, 36 : poke dc + 8, 0
120 while peek($ff00) : wend : doke $ff04 + 0, di : doke $ff04 + 2, 21 : poke $ff04 + 4, 1 : f = 1 : gosub 8100
130 while peek($ff00) : wend : doke $ff04 + 0, dc : poke $ff04 + 2, 60 : poke $ff04 + 3, 60 : poke $ff04 + 4, 12 : poke $ff04 + 5, 0 : f = 7 : gosub 8100
140 e0 = e
150 while peek($ff00) : wend : poke $ff04 + 0, 61 : poke $ff04 + 1, 59 : f = 4 : gosub 8100
160 c1 = peek($ff04 + 2)
170 p1 = peek($ff04 + 3)
180 while peek($ff00) : wend : poke $ff04 + 0, 60 : poke $ff04 + 1, 59 : f = 4 : gosub 8100
190 c2 = peek($ff04 + 2)
200 p2 = peek($ff04 + 3)
210 while peek($ff00) : wend : poke $ff04 + 0, 60 : poke $ff04 + 1, 60 : f = 4 : gosub 8100
220 c3 = peek($ff04 + 2)
230 p3 = peek($ff04 + 3)
240 while peek($ff00) : wend : doke $ff04 + 0, dc : poke $ff04 + 2, 60 : poke $ff04 + 3, 60 : poke $ff04 + 4, 3 : poke $ff04 + 5, 0 : f = 7 : gosub 8100
250 e1 = e
260 while peek($ff00) : wend : doke $ff04 + 0, dc : poke $ff04 + 2, 60 : poke $ff04 + 3, 76 : poke $ff04 + 4, 5 : poke $ff04 + 5, 0 : f = 7 : gosub 8100
270 e2 = e
280 while peek($ff00) : wend : poke $ff04 + 0, 60 : poke $ff04 + 1, 76 : f = 4 : gosub 8100
290 c4 = peek($ff04 + 2)
300 p4 = peek($ff04 + 3)
310 print "Ajout : erreur ";e0
320 print "Cel (61, 59) : couleur ";c1;", priorite ";p1
330 print "Vide (60, 59) : couleur ";c2;", priorite ";p2
340 print "Bas (60, 60) : couleur ";c3;", priorite ";p3
350 print "Priorite 3 : erreur ";e1
360 print "Priorite 5 : erreur ";e2
370 print "Point (60, 76) : couleur ";c4;", priorite ";p4
380 end
8100 ' appel 39,f, parametres deja poses ; erreur dans e
8105 g = 39
8110 poke $ff01, f : poke $ff00, g
8120 while peek($ff00) : wend : e = peek($ff02) : returnAjout : erreur 0
Cel (61, 59) : couleur 3, priorite 12
Vide (60, 59) : couleur 14, priorite 9
Bas (60, 60) : couleur 2, priorite 12
Priorite 3 : erreur 1
Priorite 5 : erreur 0
Point (60, 76) : couleur 14, priorite 9Assembleur 65C02 (64tass)
; Ajouter un cel au plan AGI (groupe 39, 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:
jsr WaitMessage
lda #<img
sta ControlPort+4
lda #>img
sta ControlPort+5
lda #<(fimg-img)
sta ControlPort+6
lda #>(fimg-img)
sta ControlPort+7
lda #1
sta ControlPort+8
lda #39
ldx #1
jsr appel
jsr WaitMessage
lda #<cel
sta ControlPort+4
lda #>cel
sta ControlPort+5
lda #60
sta ControlPort+6
lda #60
sta ControlPort+7
lda #12
sta ControlPort+8
stz ControlPort+9
lda #39
ldx #7
jsr appel
lda ControlPort+2
sta e0
jsr WaitMessage
lda #61
sta ControlPort+4
lda #59
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c1
lda ControlPort+7
sta p1
jsr WaitMessage
lda #60
sta ControlPort+4
lda #59
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c2
lda ControlPort+7
sta p2
jsr WaitMessage
lda #60
sta ControlPort+4
lda #60
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c3
lda ControlPort+7
sta p3
jsr WaitMessage
lda #<cel
sta ControlPort+4
lda #>cel
sta ControlPort+5
lda #60
sta ControlPort+6
lda #60
sta ControlPort+7
lda #3
sta ControlPort+8
stz ControlPort+9
lda #39
ldx #7
jsr appel
lda ControlPort+2
sta e1
jsr WaitMessage
lda #<cel
sta ControlPort+4
lda #>cel
sta ControlPort+5
lda #60
sta ControlPort+6
lda #76
sta ControlPort+7
lda #5
sta ControlPort+8
stz ControlPort+9
lda #39
ldx #7
jsr appel
lda ControlPort+2
sta e2
jsr WaitMessage
lda #60
sta ControlPort+4
lda #76
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c4
lda ControlPort+7
sta p4
lda #<t0
ldx #>t0
jsr ecrire
lda e0
jsr decimal
lda #13
jsr WriteCharacter
lda #<t1
ldx #>t1
jsr ecrire
lda c1
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda p1
jsr decimal
lda #13
jsr WriteCharacter
lda #<t3
ldx #>t3
jsr ecrire
lda c2
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda p2
jsr decimal
lda #13
jsr WriteCharacter
lda #<t4
ldx #>t4
jsr ecrire
lda c3
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda p3
jsr decimal
lda #13
jsr WriteCharacter
lda #<t5
ldx #>t5
jsr ecrire
lda e1
jsr decimal
lda #13
jsr WriteCharacter
lda #<t6
ldx #>t6
jsr ecrire
lda e2
jsr decimal
lda #13
jsr WriteCharacter
lda #<t7
ldx #>t7
jsr ecrire
lda c4
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda p4
jsr decimal
lda #13
jsr WriteCharacter
rts
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
; image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
img:
.byte $F0, $0C, $F2, $09, $F6, $14, $1E, $64
.byte $1E, $64, $50, $14, $50, $14, $1E, $F0
.byte $0E, $F8, $32, $32, $FF
fimg:
; cel 4 x 2, transparent = 0 : ligne du haut 0,3,3,1 ; ligne du bas 2,2,2,2 (RLE : couleur dans le quartet haut, longueur dans le bas, 0 en fin de ligne)
cel:
.byte $04, $02, $00, $01, $32, $11, $00, $24
.byte $00
fcel:
e0: .byte 0
c1: .byte 0
p1: .byte 0
c2: .byte 0
p2: .byte 0
c3: .byte 0
p3: .byte 0
e1: .byte 0
e2: .byte 0
c4: .byte 0
p4: .byte 0
t0: .text "Ajout : erreur ", 0
t1: .text "Cel (61, 59) : couleur ", 0
t2: .text ", priorite ", 0
t3: .text "Vide (60, 59) : couleur ", 0
t4: .text "Bas (60, 60) : couleur ", 0
t5: .text "Priorite 3 : erreur ", 0
t6: .text "Priorite 5 : erreur ", 0
t7: .text "Point (60, 76) : couleur ", 0Ajout : erreur 0
Cel (61, 59) : couleur 3, priorite 12
Vide (60, 59) : couleur 14, priorite 9
Bas (60, 60) : couleur 2, priorite 12
Priorite 3 : erreur 1
Priorite 5 : erreur 0
Point (60, 76) : couleur 14, priorite 939,8 Fill Plane Priority Trinity
Fixe la priorité des points d'un rectangle du plan AGI, sans changer les couleurs.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | X |
P1 | uint8 | Y |
P2 | uint8 | largeur |
P3 | uint8 | hauteur |
P4 | uint8 | priorité (0 à 15) |
| Octets | Type | Rôle |
|---|---|---|
erreur | uint8 | 1 si la largeur ou la hauteur est 0, ou la priorité supérieure à 15 |
Le rectangle est coupé aux bords du plan. Sert à la marge de add.to.pic (priorité 0 à 3). NeoBASIC n'a pas de mot-clé pour cet appel : l'exemple écrit la boîte aux lettres.
Texte de la documentation du firmware (anglais)
Trinity (T-122). Sets to Parameter:4 (0 to 15) the priority of the points of the AGI plane in the rectangle X Parameter:0, Y Parameter:1, width Parameter:2, height Parameter:3 (AGI pixels, clipped to the plane) ; the visual colours are not changed. Used for the margin of add.to.pic (priority 0 to 3). Error 1 if the width or the height is 0 or the priority is above 15.
C (llvm-mos)
/* Fixer la priorité d'un rectangle du plan (groupe 39, 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)
;
}
static void p16(uint8_t i, uint16_t v) { /* paramètre 16 bits en Pi, Pi+1 */
ControlPort.params[i] = v & 0xFF;
ControlPort.params[i + 1] = v >> 8;
}
/* image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50) */
static const uint8_t img[] = {0xF0, 0x0C, 0xF2, 0x09, 0xF6, 0x14, 0x1E, 0x64, 0x1E, 0x64, 0x50, 0x14, 0x50, 0x14, 0x1E, 0xF0, 0x0E, 0xF8, 0x32, 0x32, 0xFF};
int main(void) {
uint8_t e0, c1, p1, c2, p2, e1, e2;
libre();
p16(0, (uint16_t)img);
p16(2, sizeof img);
ControlPort.params[4] = 1;
api(39, 1);
libre();
ControlPort.params[0] = 30;
ControlPort.params[1] = 40;
ControlPort.params[2] = 10;
ControlPort.params[3] = 10;
ControlPort.params[4] = 2;
api(39, 8);
e0 = ControlPort.error;
libre();
ControlPort.params[0] = 35;
ControlPort.params[1] = 45;
api(39, 4);
c1 = ControlPort.params[2];
p1 = ControlPort.params[3];
libre();
ControlPort.params[0] = 45;
ControlPort.params[1] = 45;
api(39, 4);
c2 = ControlPort.params[2];
p2 = ControlPort.params[3];
libre();
ControlPort.params[0] = 30;
ControlPort.params[1] = 40;
ControlPort.params[2] = 10;
ControlPort.params[3] = 10;
ControlPort.params[4] = 16;
api(39, 8);
e1 = ControlPort.error;
libre();
ControlPort.params[0] = 30;
ControlPort.params[1] = 40;
ControlPort.params[2] = 0;
ControlPort.params[3] = 10;
ControlPort.params[4] = 2;
api(39, 8);
e2 = ControlPort.error;
printf("Rectangle : erreur %u\n", e0);
printf("Dedans (35, 45) : couleur %u, priorite %u\n", c1, p1);
printf("Dehors (45, 45) : couleur %u, priorite %u\n", c2, p2);
printf("Priorite 16 : erreur %u\n", e1);
printf("Largeur 0 : erreur %u\n", e2);
return 0;
}Rectangle : erreur 0
Dedans (35, 45) : couleur 14, priorite 2
Dehors (45, 45) : couleur 14, priorite 9
Priorite 16 : erreur 1
Largeur 0 : erreur 1Mad Pascal
// Fixer la priorité d'un rectangle du plan (groupe 39, fonction 8, Trinity).
program agi8;
uses crt, neo6502;
// image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
const img: array[0..20] of byte = ($F0, $0C, $F2, $09, $F6, $14, $1E, $64, $1E, $64, $50, $14, $50, $14, $1E, $F0, $0E, $F8, $32, $32, $FF);
var e0, c1, p1, c2, p2, e1, e2: byte;
procedure p16(i: byte; v: word); // paramètre 16 bits en Pi, Pi+1
begin
NeoMessage.params[i] := lo(v);
NeoMessage.params[i + 1] := hi(v);
end;
procedure appel(g, f: byte); // lance l'appel et attend la fin
begin
NeoSendMessage(g, f);
NeoWaitMessage;
end;
begin
NeoWaitMessage;
p16(0, word(@img));
p16(2, 21);
NeoMessage.params[4] := 1;
appel(39, 1);
NeoWaitMessage;
NeoMessage.params[0] := 30;
NeoMessage.params[1] := 40;
NeoMessage.params[2] := 10;
NeoMessage.params[3] := 10;
NeoMessage.params[4] := 2;
appel(39, 8);
e0 := NeoMessage.error;
NeoWaitMessage;
NeoMessage.params[0] := 35;
NeoMessage.params[1] := 45;
appel(39, 4);
c1 := NeoMessage.params[2];
p1 := NeoMessage.params[3];
NeoWaitMessage;
NeoMessage.params[0] := 45;
NeoMessage.params[1] := 45;
appel(39, 4);
c2 := NeoMessage.params[2];
p2 := NeoMessage.params[3];
NeoWaitMessage;
NeoMessage.params[0] := 30;
NeoMessage.params[1] := 40;
NeoMessage.params[2] := 10;
NeoMessage.params[3] := 10;
NeoMessage.params[4] := 16;
appel(39, 8);
e1 := NeoMessage.error;
NeoWaitMessage;
NeoMessage.params[0] := 30;
NeoMessage.params[1] := 40;
NeoMessage.params[2] := 0;
NeoMessage.params[3] := 10;
NeoMessage.params[4] := 2;
appel(39, 8);
e2 := NeoMessage.error;
writeln('Rectangle : erreur ', e0);
writeln('Dedans (35, 45) : couleur ', c1, ', priorite ', p1);
writeln('Dehors (45, 45) : couleur ', c2, ', priorite ', p2);
writeln('Priorite 16 : erreur ', e1);
writeln('Largeur 0 : erreur ', e2);
end.Rectangle : erreur 0
Dedans (35, 45) : couleur 14, priorite 2
Dehors (45, 45) : couleur 14, priorite 9
Priorite 16 : erreur 1
Largeur 0 : erreur 1NeoBASIC
10 ' Fixer la priorité d'un rectangle du plan (groupe 39, fonction 8, Trinity)
20 ' image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
30 di = alloc(21)
40 poke di + 0, 240 : poke di + 1, 12 : poke di + 2, 242 : poke di + 3, 9 : poke di + 4, 246 : poke di + 5, 20
50 poke di + 6, 30 : poke di + 7, 100 : poke di + 8, 30 : poke di + 9, 100 : poke di + 10, 80 : poke di + 11, 20
60 poke di + 12, 80 : poke di + 13, 20 : poke di + 14, 30 : poke di + 15, 240 : poke di + 16, 14 : poke di + 17, 248
70 poke di + 18, 50 : poke di + 19, 50 : poke di + 20, 255
80 while peek($ff00) : wend : doke $ff04 + 0, di : doke $ff04 + 2, 21 : poke $ff04 + 4, 1 : f = 1 : gosub 8100
90 while peek($ff00) : wend : poke $ff04 + 0, 30 : poke $ff04 + 1, 40 : poke $ff04 + 2, 10 : poke $ff04 + 3, 10 : poke $ff04 + 4, 2 : f = 8 : gosub 8100
100 e0 = e
110 while peek($ff00) : wend : poke $ff04 + 0, 35 : poke $ff04 + 1, 45 : f = 4 : gosub 8100
120 c1 = peek($ff04 + 2)
130 p1 = peek($ff04 + 3)
140 while peek($ff00) : wend : poke $ff04 + 0, 45 : poke $ff04 + 1, 45 : f = 4 : gosub 8100
150 c2 = peek($ff04 + 2)
160 p2 = peek($ff04 + 3)
170 while peek($ff00) : wend : poke $ff04 + 0, 30 : poke $ff04 + 1, 40 : poke $ff04 + 2, 10 : poke $ff04 + 3, 10 : poke $ff04 + 4, 16 : f = 8 : gosub 8100
180 e1 = e
190 while peek($ff00) : wend : poke $ff04 + 0, 30 : poke $ff04 + 1, 40 : poke $ff04 + 2, 0 : poke $ff04 + 3, 10 : poke $ff04 + 4, 2 : f = 8 : gosub 8100
200 e2 = e
210 print "Rectangle : erreur ";e0
220 print "Dedans (35, 45) : couleur ";c1;", priorite ";p1
230 print "Dehors (45, 45) : couleur ";c2;", priorite ";p2
240 print "Priorite 16 : erreur ";e1
250 print "Largeur 0 : erreur ";e2
260 end
8100 ' appel 39,f, parametres deja poses ; erreur dans e
8105 g = 39
8110 poke $ff01, f : poke $ff00, g
8120 while peek($ff00) : wend : e = peek($ff02) : returnRectangle : erreur 0
Dedans (35, 45) : couleur 14, priorite 2
Dehors (45, 45) : couleur 14, priorite 9
Priorite 16 : erreur 1
Largeur 0 : erreur 1Assembleur 65C02 (64tass)
; Fixer la priorité d'un rectangle du plan (groupe 39, 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:
jsr WaitMessage
lda #<img
sta ControlPort+4
lda #>img
sta ControlPort+5
lda #<(fimg-img)
sta ControlPort+6
lda #>(fimg-img)
sta ControlPort+7
lda #1
sta ControlPort+8
lda #39
ldx #1
jsr appel
jsr WaitMessage
lda #30
sta ControlPort+4
lda #40
sta ControlPort+5
lda #10
sta ControlPort+6
lda #10
sta ControlPort+7
lda #2
sta ControlPort+8
lda #39
ldx #8
jsr appel
lda ControlPort+2
sta e0
jsr WaitMessage
lda #35
sta ControlPort+4
lda #45
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c1
lda ControlPort+7
sta p1
jsr WaitMessage
lda #45
sta ControlPort+4
lda #45
sta ControlPort+5
lda #39
ldx #4
jsr appel
lda ControlPort+6
sta c2
lda ControlPort+7
sta p2
jsr WaitMessage
lda #30
sta ControlPort+4
lda #40
sta ControlPort+5
lda #10
sta ControlPort+6
lda #10
sta ControlPort+7
lda #16
sta ControlPort+8
lda #39
ldx #8
jsr appel
lda ControlPort+2
sta e1
jsr WaitMessage
lda #30
sta ControlPort+4
lda #40
sta ControlPort+5
stz ControlPort+6
lda #10
sta ControlPort+7
lda #2
sta ControlPort+8
lda #39
ldx #8
jsr appel
lda ControlPort+2
sta e2
lda #<t0
ldx #>t0
jsr ecrire
lda e0
jsr decimal
lda #13
jsr WriteCharacter
lda #<t1
ldx #>t1
jsr ecrire
lda c1
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda p1
jsr decimal
lda #13
jsr WriteCharacter
lda #<t3
ldx #>t3
jsr ecrire
lda c2
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda p2
jsr decimal
lda #13
jsr WriteCharacter
lda #<t4
ldx #>t4
jsr ecrire
lda e1
jsr decimal
lda #13
jsr WriteCharacter
lda #<t5
ldx #>t5
jsr ecrire
lda e2
jsr decimal
lda #13
jsr WriteCharacter
rts
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
; image AGI : ligne rouge (12) priorité 9 autour de (20,30)-(100,80), puis remplissage jaune (14) en (50,50)
img:
.byte $F0, $0C, $F2, $09, $F6, $14, $1E, $64
.byte $1E, $64, $50, $14, $50, $14, $1E, $F0
.byte $0E, $F8, $32, $32, $FF
fimg:
e0: .byte 0
c1: .byte 0
p1: .byte 0
c2: .byte 0
p2: .byte 0
e1: .byte 0
e2: .byte 0
t0: .text "Rectangle : erreur ", 0
t1: .text "Dedans (35, 45) : couleur ", 0
t2: .text ", priorite ", 0
t3: .text "Dehors (45, 45) : couleur ", 0
t4: .text "Priorite 16 : erreur ", 0
t5: .text "Largeur 0 : erreur ", 0Rectangle : erreur 0
Dedans (35, 45) : couleur 14, priorite 2
Dehors (45, 45) : couleur 14, priorite 9
Priorite 16 : erreur 1
Largeur 0 : erreur 1