Group 5 — Graphics Official
5,1 Set Defaults · 5,2 Draw Line · 5,3 Draw Rectangle · 5,4 Draw Ellipse · 5,5 Draw Pixel · 5,6 Draw Text · 5,7 Draw Image · 5,8 Draw Tilemap · 5,9 Set Graphics Mode · 5,10 Get Graphics Mode · 5,11 Set Draw Page · 5,12 Set Display Page · 5,32 Set Palette · 5,33 Read Pixel · 5,34 Reset Palette · 5,35 Set Tilemap · 5,36 Read Sprite Pixel · 5,37 Frame Count · 5,38 Get Palette · 5,39 Write Pixel · 5,40 Get Late Scanlines · 5,41 Get Bus Stalls · 5,42 Get Bus Timing · 5,64 Set Color · 5,65 Set Solid Flag · 5,66 Set Draw Size · 5,67 Set Flip Bits
Group 5 draws into graphics memory: 320 × 240 pixels in mode 0, one byte per pixel naming a palette colour. Coordinates are signed 16-bit integers (P0-P1 and P2-P3 for the first point, P4-P5 and P6-P7 for the second); whatever falls off the screen is ignored.
The colour of a drawing follows the firmware rule: new pixel = (old pixel AND mask) EXCLUSIVE OR colour. 5,1 sets mask and colour together; 5,64 sets the mask to 0, so the pixel simply takes the given colour.
Images (5,7), tile maps (5,8) and sprites (group 6) are read from a separate graphics memory, filled by loading a file at address $FFFF (3,2). This file starts with a 256-byte header: byte 0 non zero, then the numbers of 16 × 16 tiles, 16 × 16 sprites and 32 × 32 sprites; the images follow, 4 bits per pixel, left pixel in the high nibble, colour 0 being transparent. The examples build such a 384-byte file: one 16 × 16 image, left half colour 2, right half colour 5.
To check what is drawn without a screenshot, each example reads pixels back with 5,33 and prints their colour. Drawings are made at the bottom of the screen, where the console has not written anything yet.
5,1 Set Defaults Official
Sets at once the drawing mask and colour, the fill flag, the size (images and text) and the flip bits.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | mask (AND) applied to the old pixel |
P1 | uint8 | colour (EXCLUSIVE OR) |
P2 | uint8 | fill: non zero for solid shapes (and a solid background for text and images) |
P3 | uint8 | size of images and text |
P4 | uint8 | flip: bit 0 horizontal, bit 1 vertical |
Outputs: none.
New pixel = (old AND mask) EXCLUSIVE OR colour. With mask $FF, the colour is combined by EXCLUSIVE OR: drawing the same point twice brings it back to its original colour, as the example shows. In NeoBASIC, ink m, c (or ink c, mask 0), solid, frame and dim make this call.
Firmware documentation text
Configure the global graphics system settings. Not all parameters are relevant for all graphics commands; but all parameters will be set by this command. So mind their values. Refer to Section "Graphics Settings" for details.
The parameters are And, Or, Fill Flag, Extent, and Flip. Bit 0 of flip sets the horizontal flip, Bit 1 sets the vertical flip.
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Tracer deux fois le même point en OU EXCLUSIF (groupe 5, fonction 1). */
int main(void) {
neo_graphics_set_defaults(0xFF, 3, 0, 1, 0); /* Set Defaults : masque $FF, couleur 3 */
neo_graphics_draw_pixel(200, 170); /* 5,5 */
uint8_t a = neo_graphics_read_pixel(200, 170);
neo_graphics_draw_pixel(200, 170); /* même point : 3 XOR 3 = 0 */
uint8_t b = neo_graphics_read_pixel(200, 170);
printf("Premier trace : %u, second trace : %u\n", a, b);
return 0;
}Premier trace : 3, second trace : 0Mad Pascal
// Tracer deux fois le même point en OU EXCLUSIF (groupe 5, fonction 1).
program defauts;
uses crt, neo6502;
var a, b: byte;
begin
NeoSetDefaults($FF, 3, 0, 1, 0); // Set Defaults : masque $FF, couleur 3
NeoDrawPixel(200, 170); // 5,5
a := NeoGetPixel(200, 170);
NeoDrawPixel(200, 170); // même point : 3 XOR 3 = 0
b := NeoGetPixel(200, 170);
writeln('Premier trace : ', a, ', second trace : ', b);
end.Premier trace : 3, second trace : 0NeoBASIC
10 ' Tracer deux fois le meme point en OU EXCLUSIF (groupe 5, fonction 1)
20 plot 0,0 ink $ff,3 to 200,170 : a = point(200,170) : ' ink masque, couleur : 5,1
30 plot to 200,170 : b = point(200,170)
40 print "Premier trace : ";a;", second trace : ";bPremier trace : 3, second trace : 065C02 assembly (64tass)
; Tracer deux fois le même point en OU EXCLUSIF (groupe 5, fonction 1).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #$FF
sta ControlPort+4 ; P0 : masque $FF
lda #3
sta ControlPort+5 ; P1 : couleur 3
stz ControlPort+6 ; P2 : pas de remplissage
lda #1
sta ControlPort+7 ; P3 : taille 1
stz ControlPort+8 ; P4 : pas de retournement
ldx #1 ; fonction 1 : Set Defaults
jsr g5
jsr trace
sta a
jsr trace ; même point : 3 XOR 3 = 0
sta b
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Trace le point (200, 170) par 5,5 et relit sa couleur.
trace: lda #200
ldy #170
jsr point1
ldx #5 ; 5,5 : Draw Pixel
jsr g5
lda #200
ldy #170
jmp lire
; 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
a: .byte 0
b: .byte 0
t0: .text "Premier trace : ", 0
t2: .text ", second trace : ", 0Premier trace : 3, second trace : 05,2 Draw Line Official
Draws a line between two points.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | int16 | first point X |
P2-P3 | int16 | first point Y |
P4-P5 | int16 | second point X |
P6-P7 | int16 | second point Y |
Outputs: none.
In NeoBASIC, line x1,y1 to x2,y2 makes this call (with ink for the colour).
Firmware documentation text
Draw a line between the screen coordinates specified in Parameters:0,1,Parameters:2,3 (begin X,Y) and Parameters:4,5,Parameters:6,7 (end X,Y).
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Tracer une ligne horizontale (groupe 5, fonction 2). */
int main(void) {
neo_graphics_set_color(3); /* 5,64 */
neo_graphics_draw_line(150, 200, 250, 200); /* Draw Line */
uint8_t a = neo_graphics_read_pixel(200, 200);
uint8_t b = neo_graphics_read_pixel(200, 201);
printf("Sur la ligne : %u, juste dessous : %u\n", a, b);
return 0;
}Sur la ligne : 3, juste dessous : 0Mad Pascal
// Tracer une ligne horizontale (groupe 5, fonction 2).
program ligne;
uses crt, neo6502;
var a, b: byte;
begin
NeoSetColor(3); // 5,64
NeoDrawLine(150, 200, 250, 200); // Draw Line
a := NeoGetPixel(200, 200);
b := NeoGetPixel(200, 201);
writeln('Sur la ligne : ', a, ', juste dessous : ', b);
end.Sur la ligne : 3, juste dessous : 0NeoBASIC
10 ' Tracer une ligne horizontale (groupe 5, fonction 2)
20 line 150,200 ink 3 to 250,200
30 a = point(200,200) : b = point(200,201)
40 print "Sur la ligne : ";a;", juste dessous : ";bSur la ligne : 3, juste dessous : 065C02 assembly (64tass)
; Tracer une ligne horizontale (groupe 5, fonction 2).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #3
sta ControlPort+4 ; P0 : couleur 3
ldx #64 ; 5,64 : Set Color
jsr g5
lda #150
ldy #200
jsr point1 ; P0-P3 : (150, 200)
lda #250
ldy #200
jsr point2 ; P4-P7 : (250, 200)
ldx #2 ; fonction 2 : Draw Line
jsr g5
lda #200
ldy #200
jsr lire
sta a
lda #200
ldy #201
jsr lire
sta b
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; 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
a: .byte 0
b: .byte 0
t0: .text "Sur la ligne : ", 0
t2: .text ", juste dessous : ", 0Sur la ligne : 3, juste dessous : 05,3 Draw Rectangle Official
Draws a rectangle given by two opposite corners, solid or outlined depending on the fill flag.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | int16 | first point X |
P2-P3 | int16 | first point Y |
P4-P5 | int16 | second point X |
P6-P7 | int16 | second point Y |
Outputs: none.
Outline or solid depending on 5,65 (or 5,1). In NeoBASIC, rect x1,y1 to x2,y2 makes this call; frame and solid choose outline or solid.
Firmware documentation text
Draw a rectangle spanning the screen coordinates specified in Parameters:0,1,Parameters:2,3 (corner X,Y) and Parameters:4,5,Parameters:6,7 (opposite corner X,Y).
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Tracer le contour d'un rectangle (groupe 5, fonction 3). */
int main(void) {
neo_graphics_set_color(4); /* 5,64 */
neo_graphics_set_solid_flag(0); /* 5,65 : contour */
neo_graphics_draw_rectangle(150, 160, 190, 200);
uint8_t a = neo_graphics_read_pixel(150, 180);
uint8_t b = neo_graphics_read_pixel(170, 180);
printf("Bord : %u, centre : %u\n", a, b);
return 0;
}Bord : 4, centre : 0Mad Pascal
// Tracer le contour d'un rectangle (groupe 5, fonction 3).
program forme3;
uses crt, neo6502;
var a, b: byte;
begin
NeoSetColor(4); // 5,64
NeoSetSolidFlag(0); // 5,65 : contour
NeoDrawRect(150, 160, 190, 200);
a := NeoGetPixel(150, 180);
b := NeoGetPixel(170, 180);
writeln('Bord : ', a, ', centre : ', b);
end.Bord : 4, centre : 0NeoBASIC
10 ' Tracer le contour d'un rectangle (groupe 5, fonction 3)
20 rect 150,160 ink 4 frame to 190,200
30 a = point(150,180) : b = point(170,180)
40 print "Bord : ";a;", centre : ";bBord : 4, centre : 065C02 assembly (64tass)
; Tracer le contour d'un rectangle (groupe 5, fonction 3).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #4
sta ControlPort+4 ; P0 : couleur 4
ldx #64 ; 5,64 : Set Color
jsr g5
lda #0
sta ControlPort+4 ; P0 : contour
ldx #65 ; 5,65 : Set Solid Flag
jsr g5
lda #150
ldy #160
jsr point1
lda #190
ldy #200
jsr point2
ldx #3 ; 5,3
jsr g5
lda #150
ldy #180
jsr lire
sta a
lda #170
ldy #180
jsr lire
sta b
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; 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
a: .byte 0
b: .byte 0
t0: .text "Bord : ", 0
t2: .text ", centre : ", 0Bord : 4, centre : 05,4 Draw Ellipse Official
Draws the ellipse inscribed in the rectangle given by two opposite corners.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | int16 | first point X |
P2-P3 | int16 | first point Y |
P4-P5 | int16 | second point X |
P6-P7 | int16 | second point Y |
Outputs: none.
Solid or outlined depending on the fill flag (5,65). A square gives a circle. In NeoBASIC, ellipse x1,y1 to x2,y2 makes this call.
Firmware documentation text
Draw an ellipse spanning the screen coordinates specified in Parameters:0,1,Parameters:2,3 (corner X,Y) and Parameters:4,5,Parameters:6,7 (opposite corner X,Y).
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Tracer une ellipse pleine (groupe 5, fonction 4). */
int main(void) {
neo_graphics_set_color(4); /* 5,64 */
neo_graphics_set_solid_flag(1); /* 5,65 : plein */
neo_graphics_draw_ellipse(200, 160, 240, 200);
uint8_t a = neo_graphics_read_pixel(220, 180);
uint8_t b = neo_graphics_read_pixel(201, 161);
printf("Centre : %u, coin : %u\n", a, b);
return 0;
}Centre : 4, coin : 0Mad Pascal
// Tracer une ellipse pleine (groupe 5, fonction 4).
program forme4;
uses crt, neo6502;
var a, b: byte;
begin
NeoSetColor(4); // 5,64
NeoSetSolidFlag(1); // 5,65 : plein
NeoDrawEllipse(200, 160, 240, 200);
a := NeoGetPixel(220, 180);
b := NeoGetPixel(201, 161);
writeln('Centre : ', a, ', coin : ', b);
end.Centre : 4, coin : 0NeoBASIC
10 ' Tracer une ellipse pleine (groupe 5, fonction 4)
20 ellipse 200,160 ink 4 solid to 240,200
30 a = point(220,180) : b = point(201,161)
40 print "Centre : ";a;", coin : ";bCentre : 4, coin : 065C02 assembly (64tass)
; Tracer une ellipse pleine (groupe 5, fonction 4).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #4
sta ControlPort+4 ; P0 : couleur 4
ldx #64 ; 5,64 : Set Color
jsr g5
lda #1
sta ControlPort+4 ; P0 : plein
ldx #65 ; 5,65 : Set Solid Flag
jsr g5
lda #200
ldy #160
jsr point1
lda #240
ldy #200
jsr point2
ldx #4 ; 5,4
jsr g5
lda #220
ldy #180
jsr lire
sta a
lda #201
ldy #161
jsr lire
sta b
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; 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
a: .byte 0
b: .byte 0
t0: .text "Centre : ", 0
t2: .text ", coin : ", 0Centre : 4, coin : 05,5 Draw Pixel Official
Draws one pixel in the current colour.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | int16 | point X |
P2-P3 | int16 | point Y |
Outputs: none.
The pixel follows the mask/colour rule of 5,1; 5,39 instead writes a colour as is. In NeoBASIC, plot to x,y makes this call (plot x,y alone only moves the current point).
Firmware documentation text
Draw a single pixel at the screen coordinates specified in Parameters:0,1,Parameters:2,3 (X,Y).
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Allumer un pixel (groupe 5, fonction 5). */
int main(void) {
neo_graphics_set_color(6); /* 5,64 */
neo_graphics_draw_pixel(210, 170); /* 5,5 : Draw Pixel */
uint8_t a = neo_graphics_read_pixel(210, 170); /* 5,33 */
uint8_t b = neo_graphics_read_pixel(211, 170);
printf("Pixel (210, 170) : %u, voisin : %u\n", a, b);
return 0;
}Pixel (210, 170) : 6, voisin : 0Mad Pascal
// Allumer un pixel (groupe 5, fonction 5).
program pixel5;
uses crt, neo6502;
var a, b: byte;
begin
NeoSetColor(6); // 5,64
NeoDrawPixel(210, 170); // 5,5 : Draw Pixel
a := NeoGetPixel(210, 170); // 5,33
b := NeoGetPixel(211, 170);
writeln('Pixel (210, 170) : ', a, ', voisin : ', b);
end.Pixel (210, 170) : 6, voisin : 0NeoBASIC
10 ' Allumer un pixel (groupe 5, fonction 5)
20 plot 0,0 ink 6 to 210,170
30 a = point(210,170) : b = point(211,170)
40 print "Pixel (210, 170) : ";a;", voisin : ";bPixel (210, 170) : 6, voisin : 065C02 assembly (64tass)
; Allumer un pixel (groupe 5, fonction 5).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #6
sta ControlPort+4 ; P0 : couleur 6
ldx #64 ; 5,64 : Set Color
jsr g5
lda #210
ldy #170
jsr point1
ldx #5 ; 5,5 : Draw Pixel
jsr g5
lda #210
ldy #170
jsr lire ; 5,33 : Read Pixel
sta a
lda #211
ldy #170
jsr lire
sta b
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; 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
a: .byte 0
b: .byte 0
t0: .text "Pixel (210, 170) : ", 0
t2: .text ", voisin : ", 0Pixel (210, 170) : 6, voisin : 05,6 Draw Text Official
Draws a text in graphics, at a pixel position.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | int16 | top left X, in pixels |
P2-P3 | int16 | top left Y, in pixels |
P4-P5 | addr | address of the text (length-prefixed) |
Outputs: none.
The firmware documentation speaks of a character cell; the code (GFXScaledText) takes pixel coordinates, as the example confirms. Size (5,66), colour and solid background (5,65) apply. The example counts the lit pixels in a 14-pixel square around the letter A. In NeoBASIC, text "…" to x,y makes this call.
Firmware documentation text
Draw the length-prefixed string of text stored at the memory location specified in Parameters:4,5 at the screen character cell specified in Parameters:0,1,Parameters:2,3 (X,Y).
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
static uint16_t compte(uint8_t couleur, uint8_t x0, uint8_t y0, uint8_t cote) { /* pixels de cette couleur */
uint16_t n = 0;
for (uint8_t y = y0; y < y0 + cote; y++)
for (uint8_t x = x0; x < x0 + cote; x++)
if (neo_graphics_read_pixel(x, y) == couleur)
n++;
return n;
}
/* Écrire A en mode graphique et compter ses pixels (groupe 5, fonction 6). */
int main(void) {
neo_graphics_set_color(5);
neo_graphics_draw_text(200, 170, "A"); /* Draw Text */
printf("Pixels du A en couleur 5 : %u\n", compte(5, 198, 168, 14));
return 0;
}Pixels du A en couleur 5 : 16Mad Pascal
// Écrire A en mode graphique et compter ses pixels (groupe 5, fonction 6).
program texte;
uses crt, neo6502;
var s: string[4];
function compte(couleur, x0, y0, cote: byte): word; // pixels de cette couleur
var x, y: byte;
begin
result := 0;
for y := y0 to y0 + cote - 1 do
for x := x0 to x0 + cote - 1 do
if NeoGetPixel(x, y) = couleur then inc(result);
end;
begin
NeoSetColor(5);
s := 'A';
NeoDrawString(200, 170, s); // Draw Text
writeln('Pixels du A en couleur 5 : ', compte(5, 198, 168, 14));
end.Pixels du A en couleur 5 : 16NeoBASIC
10 ' Ecrire A en mode graphique et compter ses pixels (groupe 5, fonction 6)
20 text "A" dim 1 ink 5 to 200,170
30 n = 0 : for y = 168 to 181 : for x = 198 to 211
40 if point(x,y) = 5 then n = n + 1
50 next x : next y
60 print "Pixels du A en couleur 5 : ";nPixels du A en couleur 5 : 1665C02 assembly (64tass)
; Écrire A en mode graphique et compter ses pixels (groupe 5, fonction 6).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #5
sta ControlPort+4
ldx #64 ; 5,64 : couleur 5
jsr g5
lda #200
ldy #170
jsr point1 ; P0-P3 : (200, 170)
lda #<lettre
sta ControlPort+8 ; P4-P5 : texte
lda #>lettre
sta ControlPort+9
ldx #6 ; fonction 6 : Draw Text
jsr g5
jsr compte
lda #<t0
ldx #>t0
jsr ecrire
lda n
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Compte les pixels de couleur coul dans le carré (x0, y0), côté cote ; résultat dans n.
compte: stz n
lda y0
sta yc
_ly: lda x0
sta xc
_lx: lda xc
ldy yc
jsr lire
cmp coul
bne _pas
inc n
_pas: inc xc
lda xc
sec
sbc x0
cmp cote
bne _lx
inc yc
lda yc
sec
sbc y0
cmp cote
bne _ly
rts
xc: .byte 0
yc: .byte 0
n: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
lettre: .byte 1
.text "A"
coul: .byte 5
x0: .byte 198
y0: .byte 168
cote: .byte 14
t0: .text "Pixels du A en couleur 5 : ", 0Pixels du A en couleur 5 : 165,7 Draw Image Official
Draws an image from graphics memory (tile or sprite) at a given position.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | int16 | top left X |
P2-P3 | int16 | top left Y |
P4 | uint8 | image number: $00-$7F 16×16 tiles, $80-$BF 16×16 sprites, $C0-$FF 32×32 sprites |
Outputs: none.
Size (5,66), flip (5,67) and solid background (5,65) apply; colour 0 of the image is transparent unless the background is solid. With no graphics memory loaded, nothing is drawn. In NeoBASIC, image n to x,y makes this call (image n, flip dim size to x,y).
Firmware documentation text
Draw the image with image ID in Parameter:4 at the screen coordinates Parameters:0,1,Parameters:2,3 (X,Y). The extent and flip settings influence this command.
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
static uint8_t gfx[256 + 128]; /* en-tête + une image 16x16, 4 bits par pixel */
static void images(uint8_t genre) { /* 1 : une tuile ; 2 : un sprite 16x16 */
gfx[0] = 1;
gfx[genre] = 1;
for (uint8_t y = 0; y < 16; y++)
for (uint8_t i = 0; i < 8; i++)
gfx[256 + y * 8 + i] = i < 4 ? 0x22 : 0x55; /* gauche : couleur 2, droite : 5 */
neo_file_store("img.gfx", gfx, sizeof gfx);
neo_file_load("img.gfx", (void *)0xFFFF); /* $FFFF : mémoire graphique */
}
/* Dessiner une image de la mémoire graphique (groupe 5, fonction 7). */
int main(void) {
images(1);
neo_graphics_set_draw_size(1); /* 5,66 */
neo_graphics_set_flip_bits(0); /* 5,67 */
neo_graphics_draw_image(200, 160, 0); /* 5,7 : Draw Image, image 0 */
uint8_t a = neo_graphics_read_pixel(202, 165);
neo_graphics_set_draw_size(1); /* 5,66 */
neo_graphics_set_flip_bits(0); /* 5,67 */
neo_graphics_draw_image(200, 160, 0); /* 5,7 : Draw Image, image 0 */
uint8_t b = neo_graphics_read_pixel(212, 165);
printf("Gauche : %u, droite : %u\n", a, b);
return 0;
}Gauche : 2, droite : 5Mad Pascal
// Dessiner une image de la mémoire graphique (groupe 5, fonction 7).
program image7;
uses crt, neo6502;
var a, b: byte;
gfx: array[0..383] of byte; // en-tête + une image 16x16
procedure images(genre: byte); // 1 : une tuile ; 2 : un sprite 16x16
var y, i: byte;
begin
fillchar(@gfx, 384, 0);
gfx[0] := 1;
gfx[genre] := 1;
for y := 0 to 15 do
for i := 0 to 7 do
if i < 4 then gfx[256 + y * 8 + i] := $22 // gauche : couleur 2
else gfx[256 + y * 8 + i] := $55; // droite : couleur 5
NeoSave('img.gfx', word(@gfx), 384);
NeoLoad('img.gfx', $FFFF); // $FFFF : mémoire graphique
end;
begin
images(1);
NeoSetDrawSize(1); // 5,66
NeoSetFlip(0); // 5,67
NeoDrawImage(200, 160, 0); // 5,7 : Draw Image, image 0
a := NeoGetPixel(202, 165);
NeoSetDrawSize(1); // 5,66
NeoSetFlip(0); // 5,67
NeoDrawImage(200, 160, 0); // 5,7 : Draw Image, image 0
b := NeoGetPixel(212, 165);
writeln('Gauche : ', a, ', ', 'droite : ', b);
end.Gauche : 2, droite : 5NeoBASIC
10 ' Dessiner une image de la memoire graphique (groupe 5, fonction 7)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 1, 1 : ' en-tete
22 for y = 0 to 15 : for i = 0 to 7 : c = $22 : if i > 3 then c = $55
24 poke d + 256 + y * 8 + i, c : next i : next y : ' gauche : couleur 2, droite : 5
26 save "img.gfx", d, 384 : load "img.gfx", $ffff : ' $ffff : memoire graphique
30 image 0 to 200,160 : a = point(202,165)
40 image 0 to 200,160 : b = point(212,165)
50 print "Gauche : ";a; ", ";"droite : ";bGauche : 2, droite : 565C02 assembly (64tass)
; Dessiner une image de la mémoire graphique (groupe 5, fonction 7).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
jsr images
lda #1
sta ControlPort+4
ldx #66 ; 5,66 : taille 1
jsr g5
lda #0
sta ControlPort+4
ldx #67 ; 5,67 : retournement 0
jsr g5
lda #200
ldy #160
jsr point1
stz ControlPort+8 ; P4 : image 0
ldx #7 ; 5,7 : Draw Image
jsr g5
lda #202
ldy #165
jsr lire
sta a
lda #1
sta ControlPort+4
ldx #66 ; 5,66 : taille 1
jsr g5
lda #0
sta ControlPort+4
ldx #67 ; 5,67 : retournement 0
jsr g5
lda #200
ldy #160
jsr point1
stz ControlPort+8 ; P4 : image 0
ldx #7 ; 5,7 : Draw Image
jsr g5
lda #212
ldy #165
jsr lire
sta b
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda #<t3
ldx #>t3
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Enregistre gfx dans img.gfx (3,3), puis le charge en mémoire graphique (3,2 vers $FFFF).
images: jsr WaitMessage
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #<gfx
sta ControlPort+6
lda #>gfx
sta ControlPort+7
lda #<384
sta ControlPort+8
lda #>384
sta ControlPort+9
lda #3
ldx #3 ; 3,3 : Save File
jsr appel
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #$FF
sta ControlPort+6 ; $FFFF : mémoire graphique
sta ControlPort+7
lda #3
ldx #2 ; 3,2 : Load File
jmp appel
nomgfx: .byte 7
.text "img.gfx"
; 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
gfx: .byte 1, 1, 0, 0 ; en-tête : une tuile
.fill 252
.rept 16 ; 16 lignes : gauche couleur 2, droite couleur 5
.byte $22, $22, $22, $22, $55, $55, $55, $55
.endrept
a: .byte 0
b: .byte 0
t0: .text "Gauche : ", 0
t2: .text ", ", 0
t3: .text "droite : ", 0Gauche : 2, droite : 55,8 Draw Tilemap Changed by Trinity
Draws the current tile map (5,35) in a screen rectangle.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | int16 | first point X |
P2-P3 | int16 | first point Y |
P4-P5 | int16 | second point X |
P6-P7 | int16 | second point Y |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | 1 with no map, if the offset is outside the map or if the window is narrower than a tile |
Tiles are 16×16 (32×32 at size 2, see 5,66), read from graphics memory. The map has two tiles 0 side by side: we read 2 (left of the first), 5 (its right), then 2 (left of the second). The window is |x2-x1| pixels wide and |y2-y1| high: the right and bottom edges are excluded. The map starts with 3 bytes (type, width, height in tiles), then one byte per tile ($F0 transparent, $F1-$FF solid colour). With type $81 instead of 1 (Trinity), a pixel of colour 0 leaves the screen as it is, and so does the part of the window beyond the map: maps can thus be drawn over each other (parallax layers). Trinity also draws maps in modes 1 and 2. In NeoBASIC, tiledraw x1,y1 to x2,y2 makes this call.
Firmware documentation text
Draw the current tilemap at the screen coordinates specified in Parameters:0,1,Parameters:2,3 (top-left X,Y) and Parameters:4,5,Parameters:6,7 (bottom-right X,Y) using current graphics settings. The window is |x2-x1| pixels wide and |y2-y1| high : the right and bottom edges are excluded. The tilemap starts with 3 bytes : type, width, height (in tiles), then one byte per tile ($F0 transparent, $F1-$FF solid colour). Type bit 7 set ($81 rather than 1, Trinity T-92) : a pixel of colour 0 in a tile leaves the screen as it is, and so does the part of the window beyond the map, so that maps can be drawn over each other (parallax layers).
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
static uint8_t gfx[256 + 128]; /* en-tête + une image 16x16, 4 bits par pixel */
static void images(uint8_t genre) { /* 1 : une tuile ; 2 : un sprite 16x16 */
gfx[0] = 1;
gfx[genre] = 1;
for (uint8_t y = 0; y < 16; y++)
for (uint8_t i = 0; i < 8; i++)
gfx[256 + y * 8 + i] = i < 4 ? 0x22 : 0x55; /* gauche : couleur 2, droite : 5 */
neo_file_store("img.gfx", gfx, sizeof gfx);
neo_file_load("img.gfx", (void *)0xFFFF); /* $FFFF : mémoire graphique */
}
static const uint8_t carte[] = { 1, 2, 1, 0, 0 }; /* format, largeur 2, hauteur 1, tuiles 0 0 */
/* Dessiner une carte de deux tuiles (groupe 5, fonction 8). */
int main(void) {
images(1);
neo_graphics_set_tilemap(carte, 0, 0); /* 5,35 */
neo_graphics_draw_tilemap(150, 160, 182, 176); /* 5,8 : Draw Tilemap */
uint8_t a = neo_graphics_read_pixel(152, 165);
uint8_t b = neo_graphics_read_pixel(160, 165);
uint8_t c = neo_graphics_read_pixel(168, 165);
printf("Couleurs sur la ligne : %u %u %u\n", a, b, c);
return 0;
}Couleurs sur la ligne : 2 5 2Mad Pascal
// Dessiner une carte de deux tuiles (groupe 5, fonction 8).
program carte8;
uses crt, neo6502;
var a, b, c: byte;
carte: array[0..4] of byte = (1, 2, 1, 0, 0); // format, largeur 2, hauteur 1, tuiles 0 0
gfx: array[0..383] of byte; // en-tête + une image 16x16
procedure images(genre: byte); // 1 : une tuile ; 2 : un sprite 16x16
var y, i: byte;
begin
fillchar(@gfx, 384, 0);
gfx[0] := 1;
gfx[genre] := 1;
for y := 0 to 15 do
for i := 0 to 7 do
if i < 4 then gfx[256 + y * 8 + i] := $22 // gauche : couleur 2
else gfx[256 + y * 8 + i] := $55; // droite : couleur 5
NeoSave('img.gfx', word(@gfx), 384);
NeoLoad('img.gfx', $FFFF); // $FFFF : mémoire graphique
end;
begin
images(1);
NeoSelectTileMap(word(@carte), 0, 0); // 5,35
NeoDrawTileMap(150, 160, 182, 176); // 5,8 : Draw Tilemap
a := NeoGetPixel(152, 165);
b := NeoGetPixel(160, 165);
c := NeoGetPixel(168, 165);
writeln('Couleurs sur la ligne : ', a, ' ', b, ' ', c);
end.Couleurs sur la ligne : 2 5 2NeoBASIC
10 ' Dessiner une carte de deux tuiles (groupe 5, fonction 8)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 1, 1 : ' en-tete
22 for y = 0 to 15 : for i = 0 to 7 : c = $22 : if i > 3 then c = $55
24 poke d + 256 + y * 8 + i, c : next i : next y : ' gauche : couleur 2, droite : 5
26 save "img.gfx", d, 384 : load "img.gfx", $ffff : ' $ffff : memoire graphique
30 m = alloc(8) : poke m, 1 : poke m + 1, 2 : poke m + 2, 1 : poke m + 3, 0 : poke m + 4, 0 : ' carte 2 x 1
40 tilemap m, 0, 0
50 tiledraw 150,160 to 182,176
60 a = point(152,165) : b = point(160,165) : c = point(168,165)
70 print "Couleurs sur la ligne : ";a;" ";b;" ";cCouleurs sur la ligne : 2 5 265C02 assembly (64tass)
; Dessiner une carte de deux tuiles (groupe 5, fonction 8).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
jsr images
jsr WaitMessage
lda #<carte
sta ControlPort+4 ; P0-P1 : carte
lda #>carte
sta ControlPort+5
stz ControlPort+6 ; P2-P5 : décalage (0, 0)
stz ControlPort+7
stz ControlPort+8
stz ControlPort+9
ldx #35 ; 5,35 : Set Tilemap
jsr g5
lda #150
ldy #160
jsr point1
lda #182
ldy #176
jsr point2
ldx #8 ; 5,8 : Draw Tilemap
jsr g5
lda #152
ldy #165
jsr lire
sta a
lda #160
ldy #165
jsr lire
sta b
lda #168
ldy #165
jsr lire
sta c
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #<t4
ldx #>t4
jsr ecrire
lda c
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Enregistre gfx dans img.gfx (3,3), puis le charge en mémoire graphique (3,2 vers $FFFF).
images: jsr WaitMessage
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #<gfx
sta ControlPort+6
lda #>gfx
sta ControlPort+7
lda #<384
sta ControlPort+8
lda #>384
sta ControlPort+9
lda #3
ldx #3 ; 3,3 : Save File
jsr appel
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #$FF
sta ControlPort+6 ; $FFFF : mémoire graphique
sta ControlPort+7
lda #3
ldx #2 ; 3,2 : Load File
jmp appel
nomgfx: .byte 7
.text "img.gfx"
; 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
gfx: .byte 1, 1, 0, 0 ; en-tête : une tuile
.fill 252
.rept 16 ; 16 lignes : gauche couleur 2, droite couleur 5
.byte $22, $22, $22, $22, $55, $55, $55, $55
.endrept
carte: .byte 1, 2, 1, 0, 0 ; format, largeur 2, hauteur 1, tuiles 0 0
a: .byte 0
b: .byte 0
c: .byte 0
t0: .text "Couleurs sur la ligne : ", 0
t2: .text " ", 0
t4: .text " ", 0Couleurs sur la ligne : 2 5 25,9 Set Graphics Mode Trinity
Selects the display mode and resets screen, palette and console.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | mode: 0 standard 320×240 in 256 colours, 1 Hercules 720×350 monochrome, 2 trial 320×240 in 16 colours |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | non zero if the mode is unknown or not supported by the hardware |
Trinity only. Mode 2 is a trial (Trinity 0.16.58) that may change or go: 320×240 in 16 colours, two pixels per byte (the left one in the high 4 bits), two pages (5,11, 5,12), colours 0 to 15, 53×30 console; no sprite layer (sprites are drawn in XOR, as in mode 1). The fork's former 320×256 mode 2 has been removed. Sprites and images only exist in mode 0; tile maps are drawn in modes 1 and 2 too. The example switches to mode 2, reads its size back (5,10), then returns to mode 0; as the screen is cleared at each change, it keeps its results and prints them at the end.
Firmware documentation text
Select the display mode in Parameter:0 and reinitialise the screen, palette and console (F5 / ADR-02). 0 is the standard 320x240 256 colour mode. 1 is the Hercules mode (720x350 monochrome, 80x25 text in 9x14 cells). 2 is a TRIAL mode (Trinity T-90, study) : 320x240 in 16 colours, 4 bits per pixel, two pixels per byte, left pixel in the high nibble, two pages (5,11 / 5,12), palette entries 0-15, same display timing as mode 0 ; no sprite layer (sprites are drawn in XOR as in mode 1), console 53x30. It may change or go. (The fork's 320x256x16 mode 2 was removed on 2026-09-19.) Tilemaps are drawn in modes 1 and 2 too (packed path of 5,8). Sets the error flag if the mode is unknown or not supported by this hardware.
C (llvm-mos)
#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 xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
static uint8_t mode, bpp, cols, lignes;
static uint16_t largeur, hauteur;
static void lire_mode(void) { /* 5,10 : Get Graphics Mode */
libre();
api(5, 10);
mode = ControlPort.params[0];
largeur = ControlPort.params[1] | (ControlPort.params[2] << 8);
hauteur = ControlPort.params[3] | (ControlPort.params[4] << 8);
bpp = ControlPort.params[5];
cols = ControlPort.params[6];
lignes = ControlPort.params[7];
}
static uint8_t choisir(uint8_t m) { /* Set Graphics Mode, erreur rendue */
libre();
ControlPort.params[0] = m;
api(5, 9);
return ControlPort.error;
}
/* Changer de mode d'affichage (groupe 5, fonction 9, Trinity). */
int main(void) {
uint8_t e2 = choisir(2); /* essai 320x240, 16 couleurs */
lire_mode(); /* 5,10 */
uint16_t l2 = largeur, h2 = hauteur;
uint8_t e0 = choisir(0); /* retour au mode standard (écran effacé) */
lire_mode();
printf("Mode 2 : erreur %u, %u x %u\n", e2, l2, h2);
printf("Mode 0 : erreur %u, %u x %u\n", e0, largeur, hauteur);
return 0;
}Mode 2 : erreur 0, 320 x 240
Mode 0 : erreur 0, 320 x 240Mad Pascal
// Changer de mode d'affichage (groupe 5, fonction 9, Trinity).
program choisirmode;
uses crt, neo6502;
var e2, e0: byte;
largeur, hauteur, l2, h2: word;
function choisir(m: byte): byte; // Set Graphics Mode, erreur rendue
begin
NeoWaitMessage;
NeoMessage.params[0] := m;
NeoSendMessage(5, 9);
NeoWaitMessage;
result := NeoMessage.error;
end;
procedure lire_mode; // 5,10 : Get Graphics Mode
begin
NeoSendMessage(5, 10);
NeoWaitMessage;
largeur := wordxParams[0];
hauteur := wordxParams[1];
end;
begin
e2 := choisir(2); // essai 320x240, 16 couleurs
lire_mode;
l2 := largeur;
h2 := hauteur;
e0 := choisir(0); // retour au mode standard (écran effacé)
lire_mode;
writeln('Mode 2 : erreur ', e2, ', ', l2, ' x ', h2);
writeln('Mode 0 : erreur ', e0, ', ', largeur, ' x ', hauteur);
end.Mode 2 : erreur 0, 320 x 240
Mode 0 : erreur 0, 320 x 240NeoBASIC
10 ' Changer de mode d'affichage (groupe 5, fonction 9, Trinity)
20 m = 2 : gosub 1000 : e2 = e : l2 = l : h2 = h : ' essai 320x240, 16 couleurs
30 m = 0 : gosub 1000 : ' retour au mode standard (ecran efface)
40 print "Mode 2 : erreur ";e2;", ";l2;" x ";h2
50 print "Mode 0 : erreur ";e;", ";l;" x ";h
60 end
1000 ' 5,9 : mode m, erreur dans e ; puis 5,10 : largeur l, hauteur h
1010 while peek($ff00) : wend : poke $ff04, m : poke $ff01, 9 : poke $ff00, 5
1020 while peek($ff00) : wend : e = peek($ff02)
1030 poke $ff01, 10 : poke $ff00, 5
1040 while peek($ff00) : wend : l = deek($ff05) : h = deek($ff07)
1050 returnMode 2 : erreur 0, 320 x 240
Mode 0 : erreur 0, 320 x 24065C02 assembly (64tass)
; Changer de mode d'affichage (groupe 5, fonction 9, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #2 ; essai 320x240, 16 couleurs
jsr choisir
sta e2
ldy #0
jsr taille ; dimensions du mode 2 en dim
lda #0 ; retour au mode standard (écran effacé)
jsr choisir
sta e0
ldy #4
jsr taille ; dimensions du mode 0 en dim+4
lda #<t0
ldx #>t0
jsr ecrire
lda e2
jsr decimal
ldy #0
jsr montrer
lda #<t1
ldx #>t1
jsr ecrire
lda e0
jsr decimal
ldy #4
jmp montrer
; 5,10 : largeur et hauteur (P1-P4) copiées en dim+Y, à l'abri avant d'afficher.
taille: jsr WaitMessage
lda #5
ldx #10 ; 5,10 : Get Graphics Mode
jsr appel
ldx #0
_copie: lda ControlPort+5,x
sta dim,y
iny
inx
cpx #4
bne _copie
rts
; Affiche « , largeur x hauteur » des dimensions en dim+Y, puis un retour à la ligne.
montrer:
sty ou
lda #<t2
ldx #>t2
jsr ecrire
ldy ou
lda dim,y ; largeur
ldx dim+1,y
jsr decimal16
lda #<t3
ldx #>t3
jsr ecrire
ldy ou
lda dim+2,y ; hauteur
ldx dim+3,y
jsr decimal16
lda #13
jmp WriteCharacter
ou: .byte 0
; Mode A (5,9), erreur rendue dans A.
choisir:
pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0 : mode
lda #5
ldx #9 ; fonction 9 : Set Graphics Mode
jsr appel
lda ControlPort+2
rts
; Affiche en décimal le nombre de 16 bits A (poids faible) X (poids fort), jusqu'à 999.
decimal16:
stx fort
ldy #0 ; centaines
_c: sec
sbc #100
pha
lda fort
sbc #0
bcc _cf
sta fort
pla
iny
bra _c
_cf: pla
clc
adc #100
pha
tya
beq _d
ora #'0'
jsr WriteCharacter
pla
jmp decimal2
_d: pla
jmp decimal
decimal2: ; A (0-99) sur deux chiffres
ldy #0
_dz: cmp #10
bcc _u
sbc #10
iny
bra _dz
_u: pha
tya
ora #'0'
jsr WriteCharacter
pla
ora #'0'
jmp WriteCharacter
fort: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
e2: .byte 0
e0: .byte 0
dim: .fill 8
t0: .text "Mode 2 : erreur ", 0
t1: .text "Mode 0 : erreur ", 0
t2: .text ", ", 0
t3: .text " x ", 0Mode 2 : erreur 0, 320 x 240
Mode 0 : erreur 0, 320 x 2405,10 Get Graphics Mode Trinity
Gives the current display mode and its dimensions.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | mode |
P1-P2 | uint16 | width in pixels |
P3-P4 | uint16 | height in pixels |
P5 | uint8 | bits per pixel |
P6-P7 | uint8 | console: columns, then rows |
Trinity only. In mode 0: 320 × 240, 8 bits per pixel, 53-column by 30-row console (6 × 8 font).
Firmware documentation text
Return the current display mode in Parameter:0, the pixel width in Parameters:1,2, the pixel height in Parameters:3,4, the bits per pixel in Parameter:5 and the console size in characters in Parameters:6,7.
C (llvm-mos)
#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 xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
static uint8_t mode, bpp, cols, lignes;
static uint16_t largeur, hauteur;
static void lire_mode(void) { /* 5,10 : Get Graphics Mode */
libre();
api(5, 10);
mode = ControlPort.params[0];
largeur = ControlPort.params[1] | (ControlPort.params[2] << 8);
hauteur = ControlPort.params[3] | (ControlPort.params[4] << 8);
bpp = ControlPort.params[5];
cols = ControlPort.params[6];
lignes = ControlPort.params[7];
}
/* Lire le mode d'affichage (groupe 5, fonction 10, Trinity). */
int main(void) {
lire_mode();
printf("Mode %u : %u x %u, %u bits, console %u x %u\n", mode, largeur, hauteur, bpp, cols, lignes);
return 0;
}Mode 0 : 320 x 240, 8 bits, console 53 x 30Mad Pascal
// Lire le mode d'affichage (groupe 5, fonction 10, Trinity).
program litmode;
uses crt, neo6502;
var mode, bpp, cols, lignes: byte;
largeur, hauteur: word;
begin
NeoWaitMessage;
NeoSendMessage(5, 10); // Get Graphics Mode
NeoWaitMessage;
mode := NeoMessage.params[0];
largeur := wordxParams[0]; // P1-P2
hauteur := wordxParams[1]; // P3-P4
bpp := NeoMessage.params[5];
cols := NeoMessage.params[6];
lignes := NeoMessage.params[7];
writeln('Mode ', mode, ' : ', largeur, ' x ', hauteur, ', ', bpp, ' bits, console ', cols, ' x ', lignes);
end.Mode 0 : 320 x 240, 8 bits, console 53 x 30NeoBASIC
10 ' Lire le mode d'affichage (groupe 5, fonction 10, Trinity)
20 while peek($ff00) : wend : poke $ff01, 10 : poke $ff00, 5
30 while peek($ff00) : wend : m = peek($ff04) : l = peek($ff05) + 256 * peek($ff06) : h = peek($ff07) + 256 * peek($ff08)
40 b = peek($ff09) : c = peek($ff0a) : r = peek($ff0b)
50 print "Mode ";m;" : ";l;" x ";h;", ";b;" bits, console ";c;" x ";rMode 0 : 320 x 240, 8 bits, console 53 x 3065C02 assembly (64tass)
; Lire le mode d'affichage (groupe 5, fonction 10, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #5
ldx #10 ; fonction 10 : Get Graphics Mode
jsr appel
ldx #7
_copie: lda ControlPort+4,x ; P0-P7 à l'abri avant d'afficher
sta p,x
dex
bpl _copie
lda #<t0
ldx #>t0
jsr ecrire
lda p
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
lda p+1 ; 320 = $0140 : poids fort 1
ldx p+2
jsr decimal16
lda #<t2
ldx #>t2
jsr ecrire
lda p+3
ldx p+4
jsr decimal16
lda #<t3
ldx #>t3
jsr ecrire
lda p+5
jsr decimal
lda #<t4
ldx #>t4
jsr ecrire
lda p+6
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda p+7
jsr decimal
lda #13
jmp WriteCharacter
; Affiche en décimal le nombre de 16 bits A (poids faible) X (poids fort), jusqu'à 999.
decimal16:
stx fort
ldy #0 ; centaines
_c: sec
sbc #100
pha
lda fort
sbc #0
bcc _cf
sta fort
pla
iny
bra _c
_cf: pla
clc
adc #100
pha
tya
beq _d
ora #'0'
jsr WriteCharacter
pla
jmp decimal2
_d: pla
jmp decimal
decimal2: ; A (0-99) sur deux chiffres
ldy #0
_dz: cmp #10
bcc _u
sbc #10
iny
bra _dz
_u: pha
tya
ora #'0'
jsr WriteCharacter
pla
ora #'0'
jmp WriteCharacter
fort: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
p: .fill 8
t0: .text "Mode ", 0
t1: .text " : ", 0
t2: .text " x ", 0
t3: .text ", ", 0
t4: .text " bits, console ", 0Mode 0 : 320 x 240, 8 bits, console 53 x 305,11 Set Draw Page Trinity
Selects the page that the console and graphics functions draw into.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | page: 0, or 1 in modes 1 and 2 |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | non zero if the page does not exist in the current mode |
Trinity only. Mode 0 has one page, modes 1 and 2 (the 16 colour trial, see 5,9) have two: one is drawn while the other is shown (5,12). According to the Trinity 0.16.69 documentation (not tried on the bench), page n starts in video RAM at n × (bytes per line × lines), an address the blitter reaches through pages $80 and $81: in mode 2, page 1 is at $80:9600 (160 × 240); in mode 1, at $80:7B0C (90 × 350). The example, in mode 0, shows page 1 being refused.
Firmware documentation text
Select the page (Parameter:0) that console and graphics commands draw into (F-55). Mode 0 has one page, modes 1 and 2 have two (0 and 1) ; mode 2 is the 16 colour trial of T-90. Sets the error flag if the page does not exist. Page n starts at offset n x (bytes per line x lines) of the video RAM, which is what the blitter addresses as pages $80/$81 : in mode 2, page 1 is at $80:9600 (38400 = 160 x 240), so a 12,3 into the hidden page targets $80:9600 + y x 160 + x / 2, with target format 5 (even x) or 6 (odd x). In mode 1, page 1 is at $80:7B0C (31500 = 90 x 350).
C (llvm-mos)
#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 xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
static uint8_t page(uint8_t p) { /* Set Draw Page, erreur rendue */
libre();
ControlPort.params[0] = p;
api(5, 11);
return ControlPort.error;
}
/* Choisir la page où l'on dessine (groupe 5, fonction 11, Trinity). */
int main(void) {
uint8_t e1 = page(1); /* le mode 0 n'a qu'une page */
uint8_t e0 = page(0);
printf("Page 1 : erreur %u, page 0 : erreur %u\n", e1, e0);
return 0;
}Page 1 : erreur 1, page 0 : erreur 0Mad Pascal
// Choisir la page où l'on dessine (groupe 5, fonction 11, Trinity).
program page11;
uses crt, neo6502;
var e1, e0: byte;
function page(p: byte): byte; // Set Draw Page, erreur rendue
begin
NeoWaitMessage;
NeoMessage.params[0] := p;
NeoSendMessage(5, 11);
NeoWaitMessage;
result := NeoMessage.error;
end;
begin
e1 := page(1); // le mode 0 n'a qu'une page
e0 := page(0);
writeln('Page 1 : erreur ', e1, ', page 0 : erreur ', e0);
end.Page 1 : erreur 1, page 0 : erreur 0NeoBASIC
10 ' Choisir la page où l'on dessine (groupe 5, fonction 11, Trinity)
20 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 11 : poke $ff00, 5
30 while peek($ff00) : wend : e1 = peek($ff02)
40 poke $ff04, 0 : poke $ff01, 11 : poke $ff00, 5
50 while peek($ff00) : wend : e0 = peek($ff02)
60 print "Page 1 : erreur ";e1;", page 0 : erreur ";e0Page 1 : erreur 1, page 0 : erreur 065C02 assembly (64tass)
; Choisir la page où l'on dessine (groupe 5, fonction 11, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #1 ; le mode 0 n'a qu'une page
jsr page
sta e1
lda #0
jsr page
sta e0
lda #<t0
ldx #>t0
jsr ecrire
lda e1
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
lda e0
jsr decimal
lda #13
jmp WriteCharacter
; Page A (5,11), erreur rendue dans A.
page: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0 : page
lda #5
ldx #11 ; fonction 11 : Set Draw Page
jsr appel
lda ControlPort+2
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
e1: .byte 0
e0: .byte 0
t0: .text "Page 1 : erreur ", 0
t1: .text ", page 0 : erreur ", 0Page 1 : erreur 1, page 0 : erreur 05,12 Set Display Page Trinity
Selects the page shown from the next frame.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | page: 0, or 1 in modes 1 and 2 |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | non zero if the page does not exist in the current mode |
Trinity only. The change happens at the next frame: wait for 5,37 to change to be sure it is done. The example, in mode 0 (a single page), shows page 1 being refused.
Firmware documentation text
Select the page (Parameter:0) shown on screen from the next frame (F-55). Use Function 37 (Frame Count) to wait for the swap. Sets the error flag if the page does not exist.
C (llvm-mos)
#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 xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
static uint8_t page(uint8_t p) { /* Set Display Page, erreur rendue */
libre();
ControlPort.params[0] = p;
api(5, 12);
return ControlPort.error;
}
/* Choisir la page affichée (groupe 5, fonction 12, Trinity). */
int main(void) {
uint8_t e1 = page(1); /* le mode 0 n'a qu'une page */
uint8_t e0 = page(0);
printf("Page 1 : erreur %u, page 0 : erreur %u\n", e1, e0);
return 0;
}Page 1 : erreur 1, page 0 : erreur 0Mad Pascal
// Choisir la page affichée (groupe 5, fonction 12, Trinity).
program page12;
uses crt, neo6502;
var e1, e0: byte;
function page(p: byte): byte; // Set Display Page, erreur rendue
begin
NeoWaitMessage;
NeoMessage.params[0] := p;
NeoSendMessage(5, 12);
NeoWaitMessage;
result := NeoMessage.error;
end;
begin
e1 := page(1); // le mode 0 n'a qu'une page
e0 := page(0);
writeln('Page 1 : erreur ', e1, ', page 0 : erreur ', e0);
end.Page 1 : erreur 1, page 0 : erreur 0NeoBASIC
10 ' Choisir la page affichee (groupe 5, fonction 12, Trinity)
20 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 12 : poke $ff00, 5
30 while peek($ff00) : wend : e1 = peek($ff02)
40 poke $ff04, 0 : poke $ff01, 12 : poke $ff00, 5
50 while peek($ff00) : wend : e0 = peek($ff02)
60 print "Page 1 : erreur ";e1;", page 0 : erreur ";e0Page 1 : erreur 1, page 0 : erreur 065C02 assembly (64tass)
; Choisir la page affichée (groupe 5, fonction 12, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #1 ; le mode 0 n'a qu'une page
jsr page
sta e1
lda #0
jsr page
sta e0
lda #<t0
ldx #>t0
jsr ecrire
lda e1
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
lda e0
jsr decimal
lda #13
jmp WriteCharacter
; Page A (5,12), erreur rendue dans A.
page: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0 : page
lda #5
ldx #12 ; fonction 12 : Set Display Page
jsr appel
lda ControlPort+2
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
e1: .byte 0
e0: .byte 0
t0: .text "Page 1 : erreur ", 0
t1: .text ", page 0 : erreur ", 0Page 1 : erreur 1, page 0 : erreur 05,32 Set Palette Official
Changes the colour of a palette entry.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | colour number |
P1 | uint8 | red (0-255) |
P2 | uint8 | green (0-255) |
P3 | uint8 | blue (0-255) |
Outputs: none.
Everything already shown in this colour changes at once. 5,34 restores the original palette. In NeoBASIC, palette n, r, g, b makes this call.
NeoBASIC keywords that make this call: palette
Firmware documentation text
Set the palette colour at the index spcified in Parameter:0 to the values in Parameter:1,Parameter:2,Parameter:3 (RGB).
C (llvm-mos)
#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 xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
/* Changer puis relire une couleur de la palette (groupe 5, fonction 32). */
int main(void) {
neo_graphics_set_palette(5, 255, 128, 0); /* Set Palette : orange */
libre();
ControlPort.params[0] = 5;
api(5, 38); /* 5,38 : Get Palette */
printf("Couleur 5 : %u %u %u\n", ControlPort.params[1], ControlPort.params[2], ControlPort.params[3]);
neo_graphics_reset_palette(); /* 5,34 */
return 0;
}Couleur 5 : 255 128 0Mad Pascal
// Changer puis relire une couleur de la palette (groupe 5, fonction 32).
program palette;
uses crt, neo6502;
var r, g, b: byte;
begin
NeoSetPalette(5, 255, 128, 0); // Set Palette : orange
NeoGetPalette(5, r, g, b); // 5,38
NeoResetPalette; // 5,34
writeln('Couleur 5 : ', r, ' ', g, ' ', b);
end.Couleur 5 : 255 128 0NeoBASIC
10 ' Changer puis relire une couleur de la palette (groupe 5, fonction 32)
20 palette 5, 255, 128, 0
30 while peek($ff00) : wend : poke $ff04, 5 : poke $ff01, 38 : poke $ff00, 5 : ' 5,38
40 while peek($ff00) : wend : r = peek($ff05) : g = peek($ff06) : b = peek($ff07)
50 print "Couleur 5 : ";r;" ";g;" ";bCouleur 5 : 255 128 065C02 assembly (64tass)
; Changer puis relire une couleur de la palette (groupe 5, fonction 32).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #5
sta ControlPort+4 ; P0 : couleur 5
lda #255
sta ControlPort+5 ; P1-P3 : rouge, vert, bleu
lda #128
sta ControlPort+6
stz ControlPort+7
ldx #32 ; fonction 32 : Set Palette
jsr g5
lda #5
sta ControlPort+4
ldx #38 ; 5,38 : Get Palette
jsr g5
lda ControlPort+5
sta r
lda ControlPort+6
sta v
lda ControlPort+7
sta b
ldx #34 ; 5,34 : Reset Palette
jsr g5
lda #<t0
ldx #>t0
jsr ecrire
lda r
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda v
jsr decimal
lda #<t4
ldx #>t4
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; 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
r: .byte 0
v: .byte 0
b: .byte 0
t0: .text "Couleur 5 : ", 0
t2: .text " ", 0
t4: .text " ", 0Couleur 5 : 255 128 05,33 Read Pixel Official
Reads the colour of a screen pixel.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | int16 | point X |
P2-P3 | int16 | point Y |
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | colour: 0 to 255, or 0 to 15 (background only) while sprites are shown |
erreur | uint8 | 1 if the point is off screen |
While sprites are used, the firmware only returns the low 4 bits (the background); 5,36 reads the sprite layer. In NeoBASIC, point(x, y) makes this call.
NeoBASIC keywords that make this call: point()
Firmware documentation text
Read a single pixel at the screen coordinates specified in Parameters:0,1,Parameters:2,3 (X,Y). When the routine completes, the result will be in Parameter:0. If sprites are in use, this will be the background only (0..15), if sprites are not in use it may return (0..255)
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Lire la couleur d'un pixel (groupe 5, fonction 33). */
int main(void) {
neo_graphics_set_color(6); /* 5,64 */
neo_graphics_draw_pixel(210, 170); /* 5,5 */
uint8_t a = neo_graphics_read_pixel(210, 170); /* 5,33 : Read Pixel */
uint8_t b = neo_graphics_read_pixel(211, 170);
printf("Pixel (210, 170) : %u, voisin : %u\n", a, b);
return 0;
}Pixel (210, 170) : 6, voisin : 0Mad Pascal
// Lire la couleur d'un pixel (groupe 5, fonction 33).
program pixel33;
uses crt, neo6502;
var a, b: byte;
begin
NeoSetColor(6); // 5,64
NeoDrawPixel(210, 170); // 5,5
a := NeoGetPixel(210, 170); // 5,33 : Read Pixel
b := NeoGetPixel(211, 170);
writeln('Pixel (210, 170) : ', a, ', voisin : ', b);
end.Pixel (210, 170) : 6, voisin : 0NeoBASIC
10 ' Lire la couleur d'un pixel (groupe 5, fonction 33)
20 plot 0,0 ink 6 to 210,170
30 a = point(210,170) : b = point(211,170)
40 print "Pixel (210, 170) : ";a;", voisin : ";bPixel (210, 170) : 6, voisin : 065C02 assembly (64tass)
; Lire la couleur d'un pixel (groupe 5, fonction 33).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #6
sta ControlPort+4 ; P0 : couleur 6
ldx #64 ; 5,64 : Set Color
jsr g5
lda #210
ldy #170
jsr point1
ldx #5 ; 5,5 : Draw Pixel
jsr g5
lda #210
ldy #170
jsr lire ; 5,33 : Read Pixel
sta a
lda #211
ldy #170
jsr lire
sta b
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; 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
a: .byte 0
b: .byte 0
t0: .text "Pixel (210, 170) : ", 0
t2: .text ", voisin : ", 0Pixel (210, 170) : 6, voisin : 05,34 Reset Palette Official
Restores the palette to its original colours.
Inputs: none.
Outputs: none.
The example changes colour 1 to (1, 2, 3), restores the original palette and reads colour 1 back. In NeoBASIC, palette clear makes this call.
NeoBASIC keywords that make this call: palette
Firmware documentation text
Reset the palette to the defaults.
C (llvm-mos)
#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 xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
/* Changer une couleur, puis remettre la palette d'origine (groupe 5, fonction 34). */
int main(void) {
neo_graphics_set_palette(1, 1, 2, 3); /* 5,32 */
neo_graphics_reset_palette(); /* Reset Palette */
libre();
ControlPort.params[0] = 1;
api(5, 38); /* 5,38 : Get Palette */
printf("Couleur 1 remise : %u %u %u\n", ControlPort.params[1], ControlPort.params[2], ControlPort.params[3]);
return 0;
}Couleur 1 remise : 255 0 77Mad Pascal
// Changer une couleur, puis remettre la palette d'origine (groupe 5, fonction 34).
program repalette;
uses crt, neo6502;
var r, g, b: byte;
begin
NeoSetPalette(1, 1, 2, 3); // 5,32
NeoResetPalette; // Reset Palette
NeoGetPalette(1, r, g, b); // 5,38
writeln('Couleur 1 remise : ', r, ' ', g, ' ', b);
end.Couleur 1 remise : 255 0 77NeoBASIC
10 ' Changer une couleur, puis remettre la palette d'origine (groupe 5, fonction 34)
20 palette 1, 1, 2, 3
30 palette clear
40 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 38 : poke $ff00, 5 : ' 5,38
50 while peek($ff00) : wend : r = peek($ff05) : g = peek($ff06) : b = peek($ff07)
60 print "Couleur 1 remise : ";r;" ";g;" ";bCouleur 1 remise : 255 0 7765C02 assembly (64tass)
; Changer une couleur, puis remettre la palette d'origine (groupe 5, fonction 34).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
lda #1
sta ControlPort+4 ; couleur 1 := (1, 2, 3)
sta ControlPort+5
lda #2
sta ControlPort+6
lda #3
sta ControlPort+7
ldx #32 ; 5,32 : Set Palette
jsr g5
ldx #34 ; fonction 34 : Reset Palette
jsr g5
lda #1
sta ControlPort+4
ldx #38 ; 5,38 : Get Palette
jsr g5
lda ControlPort+5
sta r
lda ControlPort+6
sta v
lda ControlPort+7
sta b
lda #<t0
ldx #>t0
jsr ecrire
lda r
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda v
jsr decimal
lda #<t4
ldx #>t4
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; 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
r: .byte 0
v: .byte 0
b: .byte 0
t0: .text "Couleur 1 remise : ", 0
t2: .text " ", 0
t4: .text " ", 0Couleur 1 remise : 255 0 775,35 Set Tilemap Official
Selects the tile map, in 65C02 memory, and the starting offset in pixels.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | addr | address of the map: a format byte, width and height in tiles, then one tile number per cell, row by row |
P2-P3 | uint16 | X offset in the map, in pixels |
P4-P5 | uint16 | Y offset in the map, in pixels |
Outputs: none.
The map stays in 65C02 memory and is read again at each drawing (5,8). On Trinity, a map that runs past the end of memory is refused (T-60). In NeoBASIC, tilemap address, x, y makes this call.
NeoBASIC keywords that make this call: tilemap
Firmware documentation text
Set the current tilemap. Parameters:0,1 is the memory address of the tilemap, and Parameters:2,3,Parameters:4,5 (X,Y) specifies the offset into the tilemap, in units of pixels, of the top-left pixel of the tile.
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
static uint8_t gfx[256 + 128]; /* en-tête + une image 16x16, 4 bits par pixel */
static void images(uint8_t genre) { /* 1 : une tuile ; 2 : un sprite 16x16 */
gfx[0] = 1;
gfx[genre] = 1;
for (uint8_t y = 0; y < 16; y++)
for (uint8_t i = 0; i < 8; i++)
gfx[256 + y * 8 + i] = i < 4 ? 0x22 : 0x55; /* gauche : couleur 2, droite : 5 */
neo_file_store("img.gfx", gfx, sizeof gfx);
neo_file_load("img.gfx", (void *)0xFFFF); /* $FFFF : mémoire graphique */
}
static const uint8_t carte[] = { 1, 2, 1, 0, 0 }; /* format, largeur 2, hauteur 1, tuiles 0 0 */
/* Choisir une carte de tuiles et la dessiner (groupe 5, fonction 35). */
int main(void) {
images(1);
neo_graphics_set_tilemap(carte, 0, 0); /* 5,35 : Set Tilemap */
neo_graphics_draw_tilemap(150, 160, 182, 176); /* 5,8 */
uint8_t a = neo_graphics_read_pixel(152, 165);
uint8_t b = neo_graphics_read_pixel(160, 165);
uint8_t c = neo_graphics_read_pixel(168, 165);
printf("Couleurs sur la ligne : %u %u %u\n", a, b, c);
return 0;
}Couleurs sur la ligne : 2 5 2Mad Pascal
// Choisir une carte de tuiles et la dessiner (groupe 5, fonction 35).
program carte35;
uses crt, neo6502;
var a, b, c: byte;
carte: array[0..4] of byte = (1, 2, 1, 0, 0); // format, largeur 2, hauteur 1, tuiles 0 0
gfx: array[0..383] of byte; // en-tête + une image 16x16
procedure images(genre: byte); // 1 : une tuile ; 2 : un sprite 16x16
var y, i: byte;
begin
fillchar(@gfx, 384, 0);
gfx[0] := 1;
gfx[genre] := 1;
for y := 0 to 15 do
for i := 0 to 7 do
if i < 4 then gfx[256 + y * 8 + i] := $22 // gauche : couleur 2
else gfx[256 + y * 8 + i] := $55; // droite : couleur 5
NeoSave('img.gfx', word(@gfx), 384);
NeoLoad('img.gfx', $FFFF); // $FFFF : mémoire graphique
end;
begin
images(1);
NeoSelectTileMap(word(@carte), 0, 0); // 5,35 : Set Tilemap
NeoDrawTileMap(150, 160, 182, 176); // 5,8
a := NeoGetPixel(152, 165);
b := NeoGetPixel(160, 165);
c := NeoGetPixel(168, 165);
writeln('Couleurs sur la ligne : ', a, ' ', b, ' ', c);
end.Couleurs sur la ligne : 2 5 2NeoBASIC
10 ' Choisir une carte de tuiles et la dessiner (groupe 5, fonction 35)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 1, 1 : ' en-tete
22 for y = 0 to 15 : for i = 0 to 7 : c = $22 : if i > 3 then c = $55
24 poke d + 256 + y * 8 + i, c : next i : next y : ' gauche : couleur 2, droite : 5
26 save "img.gfx", d, 384 : load "img.gfx", $ffff : ' $ffff : memoire graphique
30 m = alloc(8) : poke m, 1 : poke m + 1, 2 : poke m + 2, 1 : poke m + 3, 0 : poke m + 4, 0 : ' carte 2 x 1
40 tilemap m, 0, 0
50 tiledraw 150,160 to 182,176
60 a = point(152,165) : b = point(160,165) : c = point(168,165)
70 print "Couleurs sur la ligne : ";a;" ";b;" ";cCouleurs sur la ligne : 2 5 265C02 assembly (64tass)
; Choisir une carte de tuiles et la dessiner (groupe 5, fonction 35).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: jsr WaitMessage
jsr images
jsr WaitMessage
lda #<carte
sta ControlPort+4 ; P0-P1 : carte
lda #>carte
sta ControlPort+5
stz ControlPort+6 ; P2-P5 : décalage (0, 0)
stz ControlPort+7
stz ControlPort+8
stz ControlPort+9
ldx #35 ; 5,35 : Set Tilemap
jsr g5
lda #150
ldy #160
jsr point1
lda #182
ldy #176
jsr point2
ldx #8 ; 5,8 : Draw Tilemap
jsr g5
lda #152
ldy #165
jsr lire
sta a
lda #160
ldy #165
jsr lire
sta b
lda #168
ldy #165
jsr lire
sta c
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #<t4
ldx #>t4
jsr ecrire
lda c
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Enregistre gfx dans img.gfx (3,3), puis le charge en mémoire graphique (3,2 vers $FFFF).
images: jsr WaitMessage
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #<gfx
sta ControlPort+6
lda #>gfx
sta ControlPort+7
lda #<384
sta ControlPort+8
lda #>384
sta ControlPort+9
lda #3
ldx #3 ; 3,3 : Save File
jsr appel
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #$FF
sta ControlPort+6 ; $FFFF : mémoire graphique
sta ControlPort+7
lda #3
ldx #2 ; 3,2 : Load File
jmp appel
nomgfx: .byte 7
.text "img.gfx"
; 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
gfx: .byte 1, 1, 0, 0 ; en-tête : une tuile
.fill 252
.rept 16 ; 16 lignes : gauche couleur 2, droite couleur 5
.byte $22, $22, $22, $22, $55, $55, $55, $55
.endrept
carte: .byte 1, 2, 1, 0, 0 ; format, largeur 2, hauteur 1, tuiles 0 0
a: .byte 0
b: .byte 0
c: .byte 0
t0: .text "Couleurs sur la ligne : ", 0
t2: .text " ", 0
t4: .text " ", 0Couleurs sur la ligne : 2 5 25,36 Read Sprite Pixel Official
Reads the colour of a pixel of the sprite layer.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | int16 | point X |
P2-P3 | int16 | point Y |
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | sprite colour (0 to 15), 0 if there is no sprite there or no sprites at all |
erreur | uint8 | 1 if the point is off screen |
Sprites use the high 4 bits of screen memory, the background the low 4 bits. The example puts sprite 0 (16×16 image, anchored at its centre) over a background pixel of colour 6: 5,36 reads the sprite, 5,33 the background. It then clears the sprites (6,1). In NeoBASIC, spoint(x, y) makes this call.
NeoBASIC keywords that make this call: spoint()
Firmware documentation text
Read Pixel from the sprite layer at the screen coordinates specified in Parameters:0,1,Parameters:2,3 (X,Y). When the routine completes, the result will be in Parameter:0. Refer to Section "Pixel Colors" for details.
C (llvm-mos)
#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 xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
static uint8_t gfx[256 + 128]; /* en-tête + une image 16x16, 4 bits par pixel */
static void images(uint8_t genre) { /* 1 : une tuile ; 2 : un sprite 16x16 */
gfx[0] = 1;
gfx[genre] = 1;
for (uint8_t y = 0; y < 16; y++)
for (uint8_t i = 0; i < 8; i++)
gfx[256 + y * 8 + i] = i < 4 ? 0x22 : 0x55; /* gauche : couleur 2, droite : 5 */
neo_file_store("img.gfx", gfx, sizeof gfx);
neo_file_load("img.gfx", (void *)0xFFFF); /* $FFFF : mémoire graphique */
}
/* Lire un pixel de sprite et le fond dessous (groupe 5, fonction 36). */
int main(void) {
images(2); /* un sprite 16x16 */
neo_graphics_set_color(6);
neo_graphics_draw_pixel(200, 170); /* fond : couleur 6 */
neo_sprite_set(0, 200, 170, 0, 0, 0); /* 6,2 : sprite 0, image 0 */
libre();
xy(0, 200, 170);
api(5, 36); /* Read Sprite Pixel */
uint8_t a = ControlPort.params[0];
uint8_t b = neo_graphics_read_pixel(200, 170);
neo_sprite_reset(); /* 6,1 */
printf("Sprite : %u, fond : %u\n", a, b);
return 0;
}Sprite : 5, fond : 6Mad Pascal
// Lire un pixel de sprite et le fond dessous (groupe 5, fonction 36).
program spoint;
uses crt, neo6502;
var a, b: byte;
gfx: array[0..383] of byte; // en-tête + une image 16x16
procedure images(genre: byte); // 1 : une tuile ; 2 : un sprite 16x16
var y, i: byte;
begin
fillchar(@gfx, 384, 0);
gfx[0] := 1;
gfx[genre] := 1;
for y := 0 to 15 do
for i := 0 to 7 do
if i < 4 then gfx[256 + y * 8 + i] := $22 // gauche : couleur 2
else gfx[256 + y * 8 + i] := $55; // droite : couleur 5
NeoSave('img.gfx', word(@gfx), 384);
NeoLoad('img.gfx', $FFFF); // $FFFF : mémoire graphique
end;
begin
images(2); // un sprite 16x16
NeoSetColor(6);
NeoDrawPixel(200, 170); // fond : couleur 6
NeoUpdateSprite(0, 200, 170, 0, 0, 0); // 6,2 : sprite 0, image 0
a := NeoGetSpritePixel(200, 170); // Read Sprite Pixel
b := NeoGetPixel(200, 170);
NeoResetSprites; // 6,1
writeln('Sprite : ', a, ', fond : ', b);
end.Sprite : 5, fond : 6NeoBASIC
10 ' Lire un pixel de sprite et le fond dessous (groupe 5, fonction 36)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 2, 1 : ' en-tete
22 for y = 0 to 15 : for i = 0 to 7 : c = $22 : if i > 3 then c = $55
24 poke d + 256 + y * 8 + i, c : next i : next y : ' gauche : couleur 2, droite : 5
26 save "img.gfx", d, 384 : load "img.gfx", $ffff : ' $ffff : memoire graphique
30 plot 0,0 ink 6 to 200,170 : ' fond : couleur 6
40 sprite 0 image $80 to 200,170 : ' $80 : premier sprite 16x16
50 a = spoint(200,170) : b = point(200,170)
60 sprite clear
70 print "Sprite : ";a;", fond : ";bSprite : 5, fond : 665C02 assembly (64tass)
; Lire un pixel de sprite et le fond dessous (groupe 5, fonction 36).
.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
jsr images ; un sprite 16x16
lda #6
sta ControlPort+4
ldx #64 ; 5,64 : couleur 6
jsr g5
lda #200
ldy #170
jsr point1
ldx #5 ; 5,5 : fond
jsr g5
stz ControlPort+4 ; P0 : sprite 0
lda #200
sta ControlPort+5 ; P1-P2 : X
stz ControlPort+6
lda #170
sta ControlPort+7 ; P3-P4 : Y
stz ControlPort+8
stz ControlPort+9 ; P5 : image 0
stz ControlPort+10 ; P6 : pas de retournement
stz ControlPort+11 ; P7 : ancre au centre
lda #6
ldx #2 ; 6,2 : Sprite Set
jsr appel
lda #200
ldy #170
jsr point1
ldx #36 ; fonction 36 : Read Sprite Pixel
jsr g5
lda ControlPort+4
sta a
lda #200
ldy #170
jsr lire
sta b
lda #6
ldx #1 ; 6,1 : Sprite Reset
jsr appel
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Enregistre gfx dans img.gfx (3,3), puis le charge en mémoire graphique (3,2 vers $FFFF).
images: jsr WaitMessage
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #<gfx
sta ControlPort+6
lda #>gfx
sta ControlPort+7
lda #<384
sta ControlPort+8
lda #>384
sta ControlPort+9
lda #3
ldx #3 ; 3,3 : Save File
jsr appel
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #$FF
sta ControlPort+6 ; $FFFF : mémoire graphique
sta ControlPort+7
lda #3
ldx #2 ; 3,2 : Load File
jmp appel
nomgfx: .byte 7
.text "img.gfx"
; 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
gfx: .byte 1, 0, 1, 0 ; en-tête : un sprite 16x16
.fill 252
.rept 16 ; 16 lignes : gauche couleur 2, droite couleur 5
.byte $22, $22, $22, $22, $55, $55, $55, $55
.endrept
a: .byte 0
b: .byte 0
t0: .text "Sprite : ", 0
t2: .text ", fond : ", 0Sprite : 5, fond : 65,37 Frame Count Official
Gives the number of screen refreshes (frames) since power-on.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0-P3 | uint32 | number of frames |
The counter changes at the start of each refresh: waiting for it to change synchronises a program with the screen (this is what NeoWaitForVblank does in Mad Pascal). The example waits for a change and prints the difference. In NeoBASIC, vblanks() makes this call.
NeoBASIC keywords that make this call: vblanks()
Firmware documentation text
Deposit into Parameters:0..3, the number of v-blanks (full screen redraws) which have occurred since power-on. This is updated at the start of each v-blank period.
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Attendre la trame suivante (groupe 5, fonction 37). */
int main(void) {
long t0 = neo_graphics_frame_count(); /* Frame Count */
long t1;
do
t1 = neo_graphics_frame_count();
while (t1 == t0);
printf("Trame suivante : ecart %ld\n", t1 - t0);
return 0;
}Trame suivante : ecart 1Mad Pascal
// Attendre la trame suivante (groupe 5, fonction 37).
program trames;
uses crt, neo6502;
var t0, t1: cardinal;
begin
t0 := NeoGetVblanks; // Frame Count
repeat
t1 := NeoGetVblanks;
until t1 <> t0;
writeln('Trame suivante : ecart ', t1 - t0);
end.Trame suivante : ecart 1NeoBASIC
10 ' Attendre la trame suivante (groupe 5, fonction 37)
20 t0 = vblanks()
30 repeat : t1 = vblanks() : until t1 <> t0
40 print "Trame suivante : ecart ";t1 - t0Trame suivante : ecart 165C02 assembly (64tass)
; Attendre la trame suivante (groupe 5, fonction 37).
.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 trame
sta t0
_att: jsr trame
cmp t0
beq _att
sec
sbc t0
pha
lda #<m
ldx #>m
jsr ecrire
pla
jsr decimal
lda #13
jmp WriteCharacter
; Octet bas du compteur de trames (5,37) dans A.
trame: jsr WaitMessage
lda #5
ldx #37 ; fonction 37 : Frame Count
jsr appel
lda ControlPort+4
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
t0: .byte 0
m: .text "Trame suivante : ecart ", 0Trame suivante : ecart 15,38 Get Palette Official
Reads the red, green and blue components of a palette entry.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | colour number |
| Bytes | Type | Meaning |
|---|---|---|
P1 | uint8 | red |
P2 | uint8 | green |
P3 | uint8 | blue |
The example reads colours 0 to 2 of the original palette. llvm-mos has no function for this call: the C example makes it directly.
Firmware documentation text
Get the palette colour at the index spcified in Parameter:0. Values are returned in Parameter:1,Parameter:2,Parameter:3 (RGB).
C (llvm-mos)
#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 xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
/* Lire les trois premières couleurs de la palette (groupe 5, fonction 38). */
int main(void) {
for (uint8_t c = 0; c < 3; c++) {
libre();
ControlPort.params[0] = c;
api(5, 38); /* Get Palette */
printf("Couleur %u : %u %u %u\n", c, ControlPort.params[1], ControlPort.params[2], ControlPort.params[3]);
}
return 0;
}Couleur 0 : 0 0 0
Couleur 1 : 255 0 0
Couleur 2 : 0 228 54Mad Pascal
// Lire les trois premières couleurs de la palette (groupe 5, fonction 38).
program litpalette;
uses crt, neo6502;
var c, r, g, b: byte;
begin
for c := 0 to 2 do
begin
NeoGetPalette(c, r, g, b); // Get Palette
writeln('Couleur ', c, ' : ', r, ' ', g, ' ', b);
end;
end.Couleur 0 : 0 0 0
Couleur 1 : 255 0 0
Couleur 2 : 0 228 54NeoBASIC
10 ' Lire les trois premieres couleurs de la palette (groupe 5, fonction 38)
20 for c = 0 to 2
30 while peek($ff00) : wend : poke $ff04, c : poke $ff01, 38 : poke $ff00, 5
40 while peek($ff00) : wend : r = peek($ff05) : g = peek($ff06) : b = peek($ff07)
50 print "Couleur ";c;" : ";r;" ";g;" ";b
60 next cCouleur 0 : 0 0 0
Couleur 1 : 255 0 0
Couleur 2 : 0 228 5465C02 assembly (64tass)
; Lire les trois premières couleurs de la palette (groupe 5, fonction 38).
.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: stz c
_suiv: jsr WaitMessage
lda c
sta ControlPort+4 ; P0 : couleur
lda #5
ldx #38 ; fonction 38 : Get Palette
jsr appel
lda #<t0
ldx #>t0
jsr ecrire
lda c
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
ldy #5
_rvb: lda ControlPort,y ; P1, P2, P3 ($FF05-$FF07)
jsr decimal
cpy #7
beq _fin
lda #' '
jsr WriteCharacter
iny
bra _rvb
_fin: lda #13
jsr WriteCharacter
inc c
lda c
cmp #3
bne _suiv
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
c: .byte 0
t0: .text "Couleur ", 0
t1: .text " : ", 0Couleur 0 : 0 0 0
Couleur 1 : 255 0 0
Couleur 2 : 0 228 545,39 Write Pixel Official
Writes a colour as is into a pixel, with no mask nor EXCLUSIVE OR.
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | int16 | point X |
P2-P3 | int16 | point Y |
P4 | uint8 | colour |
Outputs: none.
Unlike 5,5, the result does not depend on the 5,1 settings: the example sets an EXCLUSIVE OR (mask $FF, colour 3) that would change a 5,5 drawing, then writes 9 and reads 9 back.
Firmware documentation text
Write Pixel index Parameter:4 to the screen coordinate specified in Parameters:0,1,Parameters:2,3 (X,Y).
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Écrire une couleur telle quelle (groupe 5, fonction 39). */
int main(void) {
neo_graphics_set_defaults(0xFF, 3, 0, 1, 0); /* 5,1 : OU EXCLUSIF, sans effet ici */
neo_graphics_write_pixel(210, 170, 9); /* Write Pixel */
printf("Pixel ecrit : %u\n", neo_graphics_read_pixel(210, 170));
return 0;
}Pixel ecrit : 9Mad Pascal
// Écrire une couleur telle quelle (groupe 5, fonction 39).
program ecrit;
uses crt, neo6502;
var a: byte;
begin
NeoSetDefaults($FF, 3, 0, 1, 0); // 5,1 : OU EXCLUSIF, sans effet ici
NeoWritePixel(210, 170, 9); // Write Pixel
a := NeoGetPixel(210, 170);
writeln('Pixel ecrit : ', a);
end.Pixel ecrit : 9NeoBASIC
10 ' Ecrire une couleur telle quelle (groupe 5, fonction 39)
20 while peek($ff00) : wend
30 poke $ff04, 210 : poke $ff05, 0 : poke $ff06, 170 : poke $ff07, 0 : poke $ff08, 9 : poke $ff01, 39 : poke $ff00, 5
40 while peek($ff00) : wend
50 print "Pixel ecrit : ";point(210,170)Pixel ecrit : 965C02 assembly (64tass)
; Écrire une couleur telle quelle (groupe 5, fonction 39).
.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 #$FF
sta ControlPort+4 ; 5,1 : masque $FF, couleur 3 (sans effet ici)
lda #3
sta ControlPort+5
stz ControlPort+6
lda #1
sta ControlPort+7
stz ControlPort+8
ldx #1
jsr g5
lda #210
ldy #170
jsr point1
lda #9
sta ControlPort+8 ; P4 : couleur 9
ldx #39 ; fonction 39 : Write Pixel
jsr g5
lda #210
ldy #170
jsr lire
sta a
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; 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
a: .byte 0
t0: .text "Pixel ecrit : ", 0Pixel ecrit : 95,40 Get Late Scanlines Trinity
Gives the number of scanlines the second core could not produce in time since the last mode change (diagnostic).
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0-P3 | uint32 | number of late scanlines |
Trinity only (T-32c). On the board, these lines show as coloured streaks; a counter that keeps growing while a program runs means the second core is overloaded. Emulators always return 0 (value checked by the bench).
Firmware documentation text
Returns in Parameters:0-3 the number of scanlines the display could not encode in time since the last mode change (Trinity T-32c, Function 5,40, diagnostic : these show as coloured streaks on the board ; 0 in the emulators). A counter that keeps growing while a program runs means the second core is starved.
C (llvm-mos)
#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 xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
/* Lignes que l'affichage n'a pas pu produire à temps (groupe 5, fonction 40, Trinity). */
int main(void) {
libre();
api(5, 40);
printf("Lignes en retard : %lu\n", (unsigned long)(ControlPort.params[0] | ((uint32_t)ControlPort.params[1] << 8)
| ((uint32_t)ControlPort.params[2] << 16) | ((uint32_t)ControlPort.params[3] << 24)));
return 0;
}Lignes en retard : 0Mad Pascal
// Lignes que l'affichage n'a pas pu produire à temps (groupe 5, fonction 40, Trinity).
program diag40;
uses crt, neo6502;
var valeur: cardinal;
begin
NeoWaitMessage;
NeoSendMessage(5, 40);
NeoWaitMessage;
valeur := dwordParams[0];
writeln('Lignes en retard : ', valeur);
end.Lignes en retard : 0NeoBASIC
10 ' Lignes que l'affichage n'a pas pu produire à temps (groupe 5, fonction 40, Trinity)
20 while peek($ff00) : wend : poke $ff01, 40 : poke $ff00, 5
22 while peek($ff00) : wend : v0 = peek($ff04) : v1 = peek($ff05) : v2 = peek($ff06) : v = v0 + 256 * v1 + 65536 * v2
24 print "Lignes en retard : ";vLignes en retard : 065C02 assembly (64tass)
; Lignes que l'affichage n'a pas pu produire à temps (groupe 5, fonction 40, Trinity).
; L'exemple asm n'affiche que l'octet bas de chaque compteur.
.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 #5
ldx #40 ; fonction 40
jsr appel
lda ControlPort+4 ; octet bas
sta v
lda #<t0
ldx #>t0
jsr ecrire
lda v
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
v: .byte 0
t0: .text "Lignes en retard : ", 0Lignes en retard : 05,41 Get Bus Stalls Trinity
Gives one of the 6502 bus fault counters recorded by the RP2040 PIOs (diagnostic).
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | counter: 0 TXSTALL (read data not ready in time), 1 RXSTALL (address FIFO not drained in time), 2 RXUNDER (empty FIFO read) |
| Bytes | Type | Meaning |
|---|---|---|
P0-P3 | uint32 | counter value |
Trinity only (T-49, T-52). Emulators have no PIO and return 0 (value checked by the bench). The firmware documentation details the meaning of each counter.
Firmware documentation text
Returns in Parameters:0-3 one of the PIO fault counters of the 6502 bus, chosen by Parameter:0 on entry (Trinity T-49/T-52, diagnostic ; 0 in the emulators, which have no PIO) : 0 TXSTALL : the data of a read was not ready in time. 1 RXSTALL : the address FIFO was not drained in time. 2 RXUNDER : an EMPTY FIFO was read — the firmware then acts on a stale word and writes a phantom byte at a phantom address into the 6502 memory. This one corrupts the running program. 3 TXOVER : a read reply was pushed into a full FIFO and lost. The state machine generates the 6502 clock, so TXSTALL and RXSTALL merely stretch the processor and are normal while an API command is served ; RXUNDER and TXOVER are not, and any growth there is a fault. Sampled about 95 times a second, so these are windows containing at least one event, not exact counts. Pass $FF in Parameter:0 to reset all four (it then returns TXSTALL).
C (llvm-mos)
#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 xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
/* Compteurs d'incidents du bus du 6502 (groupe 5, fonction 41, Trinity). */
int main(void) {
libre();
ControlPort.params[0] = 0;
api(5, 41);
printf("TXSTALL : %lu\n", (unsigned long)(ControlPort.params[0] | ((uint32_t)ControlPort.params[1] << 8)
| ((uint32_t)ControlPort.params[2] << 16) | ((uint32_t)ControlPort.params[3] << 24)));
libre();
ControlPort.params[0] = 1;
api(5, 41);
printf("RXSTALL : %lu\n", (unsigned long)(ControlPort.params[0] | ((uint32_t)ControlPort.params[1] << 8)
| ((uint32_t)ControlPort.params[2] << 16) | ((uint32_t)ControlPort.params[3] << 24)));
libre();
ControlPort.params[0] = 2;
api(5, 41);
printf("RXUNDER : %lu\n", (unsigned long)(ControlPort.params[0] | ((uint32_t)ControlPort.params[1] << 8)
| ((uint32_t)ControlPort.params[2] << 16) | ((uint32_t)ControlPort.params[3] << 24)));
return 0;
}TXSTALL : 0
RXSTALL : 0
RXUNDER : 0Mad Pascal
// Compteurs d'incidents du bus du 6502 (groupe 5, fonction 41, Trinity).
program diag41;
uses crt, neo6502;
var valeur: cardinal;
begin
NeoWaitMessage;
NeoMessage.params[0] := 0;
NeoSendMessage(5, 41);
NeoWaitMessage;
valeur := dwordParams[0];
writeln('TXSTALL : ', valeur);
NeoWaitMessage;
NeoMessage.params[0] := 1;
NeoSendMessage(5, 41);
NeoWaitMessage;
valeur := dwordParams[0];
writeln('RXSTALL : ', valeur);
NeoWaitMessage;
NeoMessage.params[0] := 2;
NeoSendMessage(5, 41);
NeoWaitMessage;
valeur := dwordParams[0];
writeln('RXUNDER : ', valeur);
end.TXSTALL : 0
RXSTALL : 0
RXUNDER : 0NeoBASIC
10 ' Compteurs d'incidents du bus du 6502 (groupe 5, fonction 41, Trinity)
20 while peek($ff00) : wend : poke $ff04, 0 : poke $ff01, 41 : poke $ff00, 5
22 while peek($ff00) : wend : v0 = peek($ff04) : v1 = peek($ff05) : v2 = peek($ff06) : v = v0 + 256 * v1 + 65536 * v2
24 print "TXSTALL : ";v
30 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 41 : poke $ff00, 5
32 while peek($ff00) : wend : v0 = peek($ff04) : v1 = peek($ff05) : v2 = peek($ff06) : v = v0 + 256 * v1 + 65536 * v2
34 print "RXSTALL : ";v
40 while peek($ff00) : wend : poke $ff04, 2 : poke $ff01, 41 : poke $ff00, 5
42 while peek($ff00) : wend : v0 = peek($ff04) : v1 = peek($ff05) : v2 = peek($ff06) : v = v0 + 256 * v1 + 65536 * v2
44 print "RXUNDER : ";vTXSTALL : 0
RXSTALL : 0
RXUNDER : 065C02 assembly (64tass)
; Compteurs d'incidents du bus du 6502 (groupe 5, fonction 41, Trinity).
; L'exemple asm n'affiche que l'octet bas de chaque compteur.
.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 #0
sta ControlPort+4 ; P0 : compteur choisi
lda #5
ldx #41 ; fonction 41
jsr appel
lda ControlPort+4 ; octet bas
sta v
lda #<t0
ldx #>t0
jsr ecrire
lda v
jsr decimal
lda #13
jsr WriteCharacter
jsr WaitMessage
lda #1
sta ControlPort+4 ; P0 : compteur choisi
lda #5
ldx #41 ; fonction 41
jsr appel
lda ControlPort+4 ; octet bas
sta v
lda #<t1
ldx #>t1
jsr ecrire
lda v
jsr decimal
lda #13
jsr WriteCharacter
jsr WaitMessage
lda #2
sta ControlPort+4 ; P0 : compteur choisi
lda #5
ldx #41 ; fonction 41
jsr appel
lda ControlPort+4 ; octet bas
sta v
lda #<t2
ldx #>t2
jsr ecrire
lda v
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
v: .byte 0
t0: .text "TXSTALL : ", 0
t1: .text "RXSTALL : ", 0
t2: .text "RXUNDER : ", 0TXSTALL : 0
RXSTALL : 0
RXUNDER : 05,42 Get Bus Timing Trinity
Gives a timing measure (diagnostic, T-50 and T-90): the longest synchronisation, the longest API command, or a display measure.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | 0: longest DSPSync (keyboard, USB, blink); 1: longest API command; display side (core 1): 2 longest processing of one line, 3 longest gap between two line callbacks (nominal: 32 in mode 1, 63 in modes 0 and 2, where each line is doubled and the callback runs every other line), 4 number of callbacks late by more than twice that nominal gap |
| Bytes | Type | Meaning |
|---|---|---|
P0-P3 | uint32 | duration in microseconds (0 to 3) or number of lines (4) |
Trinity only (T-50). During these times, the firmware is away from the 6502 bus and the processor clock is stopped: normal for an API call, abnormal if it lasts. The bench emulator returns 0; its values do not measure the board.
Firmware documentation text
Returns in Parameters:0-3 a bus timing measure of Trinity T-50, chosen by Parameter:0 on entry : 0 the longest DSPSync ever seen in microseconds (keyboard, USB task, blink), 1 the longest API command (DSPHandler) ; Trinity T-90 adds the display side, core 1 : 2 the longest scanline callback (conversion of one line into the scan buffer), 3 the longest gap between two scanline callbacks (nominal : 32 in mode 1, whose lines are native, but 63 in modes 0 and 2, whose lines are doubled : the callback runs every other line), 4 the number of callbacks late by more than twice that nominal gap. 0 and 1 are the time the firmware spends away from the 6502 bus : while it is there the PIO stalls and the processor clock stops, which is normal for an API call and pathological when it lasts. Counts of stalls alone (Function 5,41) cannot tell the two apart, hence these. Reset with 5,41 and $FF. 0 in the emulators.
C (llvm-mos)
#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 xy(uint8_t i, uint16_t x, uint16_t y) { /* point (x, y) en Pi..Pi+3 */
ControlPort.params[i] = x & 0xFF;
ControlPort.params[i + 1] = x >> 8;
ControlPort.params[i + 2] = y & 0xFF;
ControlPort.params[i + 3] = y >> 8;
}
/* Durées pendant lesquelles le firmware quitte le bus (groupe 5, fonction 42, Trinity). */
int main(void) {
libre();
ControlPort.params[0] = 0;
api(5, 42);
printf("DSPSync le plus long : %lu\n", (unsigned long)(ControlPort.params[0] | ((uint32_t)ControlPort.params[1] << 8)
| ((uint32_t)ControlPort.params[2] << 16) | ((uint32_t)ControlPort.params[3] << 24)));
libre();
ControlPort.params[0] = 1;
api(5, 42);
printf("Commande la plus longue : %lu\n", (unsigned long)(ControlPort.params[0] | ((uint32_t)ControlPort.params[1] << 8)
| ((uint32_t)ControlPort.params[2] << 16) | ((uint32_t)ControlPort.params[3] << 24)));
return 0;
}DSPSync le plus long : 0
Commande la plus longue : 0Mad Pascal
// Durées pendant lesquelles le firmware quitte le bus (groupe 5, fonction 42, Trinity).
program diag42;
uses crt, neo6502;
var valeur: cardinal;
begin
NeoWaitMessage;
NeoMessage.params[0] := 0;
NeoSendMessage(5, 42);
NeoWaitMessage;
valeur := dwordParams[0];
writeln('DSPSync le plus long : ', valeur);
NeoWaitMessage;
NeoMessage.params[0] := 1;
NeoSendMessage(5, 42);
NeoWaitMessage;
valeur := dwordParams[0];
writeln('Commande la plus longue : ', valeur);
end.DSPSync le plus long : 0
Commande la plus longue : 0NeoBASIC
10 ' Durees pendant lesquelles le firmware quitte le bus (groupe 5, fonction 42, Trinity)
20 while peek($ff00) : wend : poke $ff04, 0 : poke $ff01, 42 : poke $ff00, 5
22 while peek($ff00) : wend : v0 = peek($ff04) : v1 = peek($ff05) : v2 = peek($ff06) : v = v0 + 256 * v1 + 65536 * v2
24 print "DSPSync le plus long : ";v
30 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 42 : poke $ff00, 5
32 while peek($ff00) : wend : v0 = peek($ff04) : v1 = peek($ff05) : v2 = peek($ff06) : v = v0 + 256 * v1 + 65536 * v2
34 print "Commande la plus longue : ";vDSPSync le plus long : 0
Commande la plus longue : 065C02 assembly (64tass)
; Durées pendant lesquelles le firmware quitte le bus (groupe 5, fonction 42, Trinity).
; L'exemple asm n'affiche que l'octet bas de chaque compteur.
.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 #0
sta ControlPort+4 ; P0 : compteur choisi
lda #5
ldx #42 ; fonction 42
jsr appel
lda ControlPort+4 ; octet bas
sta v
lda #<t0
ldx #>t0
jsr ecrire
lda v
jsr decimal
lda #13
jsr WriteCharacter
jsr WaitMessage
lda #1
sta ControlPort+4 ; P0 : compteur choisi
lda #5
ldx #42 ; fonction 42
jsr appel
lda ControlPort+4 ; octet bas
sta v
lda #<t1
ldx #>t1
jsr ecrire
lda v
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
v: .byte 0
t0: .text "DSPSync le plus long : ", 0
t1: .text "Commande la plus longue : ", 0DSPSync le plus long : 0
Commande la plus longue : 05,64 Set Color Official
Selects the colour of the following drawings (mask set to 0).
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | colour |
Outputs: none.
Same as 5,1 with a mask of 0 and the given colour, leaving the other settings alone. NeoBASIC does not make this call (ink c makes 5,1): the BASIC example writes it with poke.
Firmware documentation text
Set Color Sets the current drawing colour to Parameter:0
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Choisir la couleur de tracé (groupe 5, fonction 64). */
int main(void) {
neo_graphics_set_color(6); /* 5,64 : Set Color */
neo_graphics_draw_pixel(210, 170); /* 5,5 */
uint8_t a = neo_graphics_read_pixel(210, 170); /* 5,33 */
uint8_t b = neo_graphics_read_pixel(211, 170);
printf("Pixel (210, 170) : %u, voisin : %u\n", a, b);
return 0;
}Pixel (210, 170) : 6, voisin : 0Mad Pascal
// Choisir la couleur de tracé (groupe 5, fonction 64).
program pixel64;
uses crt, neo6502;
var a, b: byte;
begin
NeoSetColor(6); // 5,64 : Set Color
NeoDrawPixel(210, 170); // 5,5
a := NeoGetPixel(210, 170); // 5,33
b := NeoGetPixel(211, 170);
writeln('Pixel (210, 170) : ', a, ', voisin : ', b);
end.Pixel (210, 170) : 6, voisin : 0NeoBASIC
10 ' Choisir la couleur de trace (groupe 5, fonction 64)
20 while peek($ff00) : wend : poke $ff04, 6 : poke $ff01, 64 : poke $ff00, 5 : ' Set Color
25 plot to 210,170
30 a = point(210,170) : b = point(211,170)
40 print "Pixel (210, 170) : ";a;", voisin : ";bPixel (210, 170) : 6, voisin : 065C02 assembly (64tass)
; Choisir la couleur de tracé (groupe 5, fonction 64).
.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 #6
sta ControlPort+4 ; P0 : couleur 6
ldx #64 ; 5,64 : Set Color
jsr g5
lda #210
ldy #170
jsr point1
ldx #5 ; 5,5 : Draw Pixel
jsr g5
lda #210
ldy #170
jsr lire ; 5,33 : Read Pixel
sta a
lda #211
ldy #170
jsr lire
sta b
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; 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
a: .byte 0
b: .byte 0
t0: .text "Pixel (210, 170) : ", 0
t2: .text ", voisin : ", 0Pixel (210, 170) : 6, voisin : 05,65 Set Solid Flag Official
Sets the fill flag: solid shapes, and a solid background for text and images.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | 0: outline (transparent background); non zero: solid |
Outputs: none.
In NeoBASIC, frame and solid make 5,1 with this flag.
Firmware documentation text
Set Solid Flag
Sets the solid flag to Parameter:0, which indicates either solid fill (for shapes) or solid background (for images and fonts)
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Le même rectangle en contour puis plein (groupe 5, fonction 65). */
int main(void) {
neo_graphics_set_color(4);
neo_graphics_set_solid_flag(0); /* Set Solid Flag : contour */
neo_graphics_draw_rectangle(150, 160, 190, 200);
uint8_t a = neo_graphics_read_pixel(170, 180); /* centre */
neo_graphics_set_solid_flag(1); /* plein */
neo_graphics_draw_rectangle(150, 160, 190, 200);
uint8_t b = neo_graphics_read_pixel(170, 180);
printf("Contour : %u, plein : %u\n", a, b);
return 0;
}Contour : 0, plein : 4Mad Pascal
// Le même rectangle en contour puis plein (groupe 5, fonction 65).
program remplir;
uses crt, neo6502;
var a, b: byte;
begin
NeoSetColor(4);
NeoSetSolidFlag(0); // Set Solid Flag : contour
NeoDrawRect(150, 160, 190, 200);
a := NeoGetPixel(170, 180); // centre
NeoSetSolidFlag(1); // plein
NeoDrawRect(150, 160, 190, 200);
b := NeoGetPixel(170, 180);
writeln('Contour : ', a, ', plein : ', b);
end.Contour : 0, plein : 4NeoBASIC
10 ' Le meme rectangle en contour puis plein (groupe 5, fonction 65)
20 while peek($ff00) : wend : poke $ff04, 0 : poke $ff01, 65 : poke $ff00, 5 : ' contour
30 rect 150,160 ink 4 to 190,200 : a = point(170,180)
40 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 65 : poke $ff00, 5 : ' plein
50 rect 150,160 to 190,200 : b = point(170,180)
60 print "Contour : ";a;", plein : ";bContour : 0, plein : 465C02 assembly (64tass)
; Le même rectangle en contour puis plein (groupe 5, fonction 65).
.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 #4
sta ControlPort+4
ldx #64 ; 5,64 : couleur 4
jsr g5
lda #0
jsr rect ; contour
sta a
lda #1
jsr rect ; plein
sta b
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Drapeau A (5,65), rectangle (150, 160)-(190, 200), couleur du centre dans A.
rect: sta ControlPort+4
ldx #65 ; fonction 65 : Set Solid Flag
jsr g5
lda #150
ldy #160
jsr point1
lda #190
ldy #200
jsr point2
ldx #3 ; 5,3 : rectangle
jsr g5
lda #170
ldy #180
jmp lire
; 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
a: .byte 0
b: .byte 0
t0: .text "Contour : ", 0
t2: .text ", plein : ", 0Contour : 0, plein : 45,66 Set Draw Size Official
Selects the size (scale factor) of images and text.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | size: 1 normal, 2 double… |
Outputs: none.
The point read is 20 pixels right of the corner: outside the image at size 1 (16 pixels wide), in its right half at size 2 (32 pixels). Size 2 is also used for 32×32 tile maps (5,8). In NeoBASIC, dim n makes 5,1 with this size.
Firmware documentation text
Set Draw Size
Sets the drawing scale for images and fonts to Parameter:0
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
static uint8_t gfx[256 + 128]; /* en-tête + une image 16x16, 4 bits par pixel */
static void images(uint8_t genre) { /* 1 : une tuile ; 2 : un sprite 16x16 */
gfx[0] = 1;
gfx[genre] = 1;
for (uint8_t y = 0; y < 16; y++)
for (uint8_t i = 0; i < 8; i++)
gfx[256 + y * 8 + i] = i < 4 ? 0x22 : 0x55; /* gauche : couleur 2, droite : 5 */
neo_file_store("img.gfx", gfx, sizeof gfx);
neo_file_load("img.gfx", (void *)0xFFFF); /* $FFFF : mémoire graphique */
}
/* Dessiner une image en taille 1 puis 2 (groupe 5, fonction 66). */
int main(void) {
images(1);
neo_graphics_set_draw_size(1); /* 5,66 : Set Draw Size */
neo_graphics_set_flip_bits(0); /* 5,67 */
neo_graphics_draw_image(150, 160, 0); /* 5,7, image 0 */
uint8_t a = neo_graphics_read_pixel(170, 165);
neo_graphics_set_draw_size(2); /* 5,66 : Set Draw Size */
neo_graphics_set_flip_bits(0); /* 5,67 */
neo_graphics_draw_image(200, 160, 0); /* 5,7, image 0 */
uint8_t b = neo_graphics_read_pixel(220, 165);
printf("Taille 1 : %u, taille 2 : %u\n", a, b);
return 0;
}Taille 1 : 0, taille 2 : 5Mad Pascal
// Dessiner une image en taille 1 puis 2 (groupe 5, fonction 66).
program image66;
uses crt, neo6502;
var a, b: byte;
gfx: array[0..383] of byte; // en-tête + une image 16x16
procedure images(genre: byte); // 1 : une tuile ; 2 : un sprite 16x16
var y, i: byte;
begin
fillchar(@gfx, 384, 0);
gfx[0] := 1;
gfx[genre] := 1;
for y := 0 to 15 do
for i := 0 to 7 do
if i < 4 then gfx[256 + y * 8 + i] := $22 // gauche : couleur 2
else gfx[256 + y * 8 + i] := $55; // droite : couleur 5
NeoSave('img.gfx', word(@gfx), 384);
NeoLoad('img.gfx', $FFFF); // $FFFF : mémoire graphique
end;
begin
images(1);
NeoSetDrawSize(1); // 5,66 : Set Draw Size
NeoSetFlip(0); // 5,67
NeoDrawImage(150, 160, 0); // 5,7, image 0
a := NeoGetPixel(170, 165);
NeoSetDrawSize(2); // 5,66 : Set Draw Size
NeoSetFlip(0); // 5,67
NeoDrawImage(200, 160, 0); // 5,7, image 0
b := NeoGetPixel(220, 165);
writeln('Taille 1 : ', a, ', ', 'taille 2 : ', b);
end.Taille 1 : 0, taille 2 : 5NeoBASIC
10 ' Dessiner une image en taille 1 puis 2 (groupe 5, fonction 66)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 1, 1 : ' en-tete
22 for y = 0 to 15 : for i = 0 to 7 : c = $22 : if i > 3 then c = $55
24 poke d + 256 + y * 8 + i, c : next i : next y : ' gauche : couleur 2, droite : 5
26 save "img.gfx", d, 384 : load "img.gfx", $ffff : ' $ffff : memoire graphique
30 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 66 : poke $ff00, 5 : ' taille
31 while peek($ff00) : wend : poke $ff04, 0 : poke $ff01, 67 : poke $ff00, 5 : ' retournement
32 while peek($ff00) : wend : poke $ff04, 150 : poke $ff05, 0 : poke $ff06, 160 : poke $ff07, 0 : poke $ff08, 0 : poke $ff01, 7 : poke $ff00, 5
33 while peek($ff00) : wend : a = point(170,165)
40 while peek($ff00) : wend : poke $ff04, 2 : poke $ff01, 66 : poke $ff00, 5 : ' taille
41 while peek($ff00) : wend : poke $ff04, 0 : poke $ff01, 67 : poke $ff00, 5 : ' retournement
42 while peek($ff00) : wend : poke $ff04, 200 : poke $ff05, 0 : poke $ff06, 160 : poke $ff07, 0 : poke $ff08, 0 : poke $ff01, 7 : poke $ff00, 5
43 while peek($ff00) : wend : b = point(220,165)
50 print "Taille 1 : ";a; ", ";"taille 2 : ";bTaille 1 : 0, taille 2 : 565C02 assembly (64tass)
; Dessiner une image en taille 1 puis 2 (groupe 5, fonction 66).
.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
jsr images
lda #1
sta ControlPort+4
ldx #66 ; 5,66 : taille 1
jsr g5
lda #0
sta ControlPort+4
ldx #67 ; 5,67 : retournement 0
jsr g5
lda #150
ldy #160
jsr point1
stz ControlPort+8 ; P4 : image 0
ldx #7 ; 5,7 : Draw Image
jsr g5
lda #170
ldy #165
jsr lire
sta a
lda #2
sta ControlPort+4
ldx #66 ; 5,66 : taille 2
jsr g5
lda #0
sta ControlPort+4
ldx #67 ; 5,67 : retournement 0
jsr g5
lda #200
ldy #160
jsr point1
stz ControlPort+8 ; P4 : image 0
ldx #7 ; 5,7 : Draw Image
jsr g5
lda #220
ldy #165
jsr lire
sta b
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda #<t3
ldx #>t3
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Enregistre gfx dans img.gfx (3,3), puis le charge en mémoire graphique (3,2 vers $FFFF).
images: jsr WaitMessage
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #<gfx
sta ControlPort+6
lda #>gfx
sta ControlPort+7
lda #<384
sta ControlPort+8
lda #>384
sta ControlPort+9
lda #3
ldx #3 ; 3,3 : Save File
jsr appel
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #$FF
sta ControlPort+6 ; $FFFF : mémoire graphique
sta ControlPort+7
lda #3
ldx #2 ; 3,2 : Load File
jmp appel
nomgfx: .byte 7
.text "img.gfx"
; 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
gfx: .byte 1, 1, 0, 0 ; en-tête : une tuile
.fill 252
.rept 16 ; 16 lignes : gauche couleur 2, droite couleur 5
.byte $22, $22, $22, $22, $55, $55, $55, $55
.endrept
a: .byte 0
b: .byte 0
t0: .text "Taille 1 : ", 0
t2: .text ", ", 0
t3: .text "taille 2 : ", 0Taille 1 : 0, taille 2 : 55,67 Set Flip Bits Official
Sets the flipping of images: bit 0 horizontal, bit 1 vertical.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | bit 0: horizontal mirror; bit 1: vertical mirror |
Outputs: none.
The image has its left half in colour 2: flipped horizontally, it shows colour 5 there. In NeoBASIC, image n, flip to x,y makes 5,1 with this setting.
Firmware documentation text
Set Flip Bits Sets the flip bits for drawing images. Bit 0 set causes a horizontal flip, bit 1 set causes a vertical flip.
C (llvm-mos)
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
static uint8_t gfx[256 + 128]; /* en-tête + une image 16x16, 4 bits par pixel */
static void images(uint8_t genre) { /* 1 : une tuile ; 2 : un sprite 16x16 */
gfx[0] = 1;
gfx[genre] = 1;
for (uint8_t y = 0; y < 16; y++)
for (uint8_t i = 0; i < 8; i++)
gfx[256 + y * 8 + i] = i < 4 ? 0x22 : 0x55; /* gauche : couleur 2, droite : 5 */
neo_file_store("img.gfx", gfx, sizeof gfx);
neo_file_load("img.gfx", (void *)0xFFFF); /* $FFFF : mémoire graphique */
}
/* Dessiner une image retournée (groupe 5, fonction 67). */
int main(void) {
images(1);
neo_graphics_set_draw_size(1); /* 5,66 */
neo_graphics_set_flip_bits(0); /* 5,67 : Set Flip Bits */
neo_graphics_draw_image(150, 160, 0); /* 5,7, image 0 */
uint8_t a = neo_graphics_read_pixel(152, 165);
neo_graphics_set_draw_size(1); /* 5,66 */
neo_graphics_set_flip_bits(1); /* 5,67 : Set Flip Bits */
neo_graphics_draw_image(200, 160, 0); /* 5,7, image 0 */
uint8_t b = neo_graphics_read_pixel(202, 165);
printf("Normale : %u, retournee : %u\n", a, b);
return 0;
}Normale : 2, retournee : 5Mad Pascal
// Dessiner une image retournée (groupe 5, fonction 67).
program image67;
uses crt, neo6502;
var a, b: byte;
gfx: array[0..383] of byte; // en-tête + une image 16x16
procedure images(genre: byte); // 1 : une tuile ; 2 : un sprite 16x16
var y, i: byte;
begin
fillchar(@gfx, 384, 0);
gfx[0] := 1;
gfx[genre] := 1;
for y := 0 to 15 do
for i := 0 to 7 do
if i < 4 then gfx[256 + y * 8 + i] := $22 // gauche : couleur 2
else gfx[256 + y * 8 + i] := $55; // droite : couleur 5
NeoSave('img.gfx', word(@gfx), 384);
NeoLoad('img.gfx', $FFFF); // $FFFF : mémoire graphique
end;
begin
images(1);
NeoSetDrawSize(1); // 5,66
NeoSetFlip(0); // 5,67 : Set Flip Bits
NeoDrawImage(150, 160, 0); // 5,7, image 0
a := NeoGetPixel(152, 165);
NeoSetDrawSize(1); // 5,66
NeoSetFlip(1); // 5,67 : Set Flip Bits
NeoDrawImage(200, 160, 0); // 5,7, image 0
b := NeoGetPixel(202, 165);
writeln('Normale : ', a, ', ', 'retournee : ', b);
end.Normale : 2, retournee : 5NeoBASIC
10 ' Dessiner une image retournee (groupe 5, fonction 67)
20 d = alloc(384) : for i = 0 to 383 : poke d + i, 0 : next i : poke d, 1 : poke d + 1, 1 : ' en-tete
22 for y = 0 to 15 : for i = 0 to 7 : c = $22 : if i > 3 then c = $55
24 poke d + 256 + y * 8 + i, c : next i : next y : ' gauche : couleur 2, droite : 5
26 save "img.gfx", d, 384 : load "img.gfx", $ffff : ' $ffff : memoire graphique
30 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 66 : poke $ff00, 5 : ' taille
31 while peek($ff00) : wend : poke $ff04, 0 : poke $ff01, 67 : poke $ff00, 5 : ' retournement
32 while peek($ff00) : wend : poke $ff04, 150 : poke $ff05, 0 : poke $ff06, 160 : poke $ff07, 0 : poke $ff08, 0 : poke $ff01, 7 : poke $ff00, 5
33 while peek($ff00) : wend : a = point(152,165)
40 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 66 : poke $ff00, 5 : ' taille
41 while peek($ff00) : wend : poke $ff04, 1 : poke $ff01, 67 : poke $ff00, 5 : ' retournement
42 while peek($ff00) : wend : poke $ff04, 200 : poke $ff05, 0 : poke $ff06, 160 : poke $ff07, 0 : poke $ff08, 0 : poke $ff01, 7 : poke $ff00, 5
43 while peek($ff00) : wend : b = point(202,165)
50 print "Normale : ";a; ", ";"retournee : ";bNormale : 2, retournee : 565C02 assembly (64tass)
; Dessiner une image retournée (groupe 5, fonction 67).
.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
jsr images
lda #1
sta ControlPort+4
ldx #66 ; 5,66 : taille 1
jsr g5
lda #0
sta ControlPort+4
ldx #67 ; 5,67 : retournement 0
jsr g5
lda #150
ldy #160
jsr point1
stz ControlPort+8 ; P4 : image 0
ldx #7 ; 5,7 : Draw Image
jsr g5
lda #152
ldy #165
jsr lire
sta a
lda #1
sta ControlPort+4
ldx #66 ; 5,66 : taille 1
jsr g5
lda #1
sta ControlPort+4
ldx #67 ; 5,67 : retournement 1
jsr g5
lda #200
ldy #160
jsr point1
stz ControlPort+8 ; P4 : image 0
ldx #7 ; 5,7 : Draw Image
jsr g5
lda #202
ldy #165
jsr lire
sta b
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t2
ldx #>t2
jsr ecrire
lda #<t3
ldx #>t3
jsr ecrire
lda b
jsr decimal
lda #13
jmp WriteCharacter
; Point (A, Y) en P0-P3, point2 en P4-P7 (coordonnées inférieures à 256).
point1: sta ControlPort+4
stz ControlPort+5
sty ControlPort+6
stz ControlPort+7
rts
point2: sta ControlPort+8
stz ControlPort+9
sty ControlPort+10
stz ControlPort+11
rts
; Couleur du pixel (A, Y), lue par 5,33, rendue dans A.
lire: pha
jsr WaitMessage
pla
jsr point1
lda #5
ldx #33 ; 5,33 : Read Pixel
jsr appel
lda ControlPort+4
rts
; Appel du groupe 5, fonction X.
g5: lda #5
jmp appel
; Enregistre gfx dans img.gfx (3,3), puis le charge en mémoire graphique (3,2 vers $FFFF).
images: jsr WaitMessage
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #<gfx
sta ControlPort+6
lda #>gfx
sta ControlPort+7
lda #<384
sta ControlPort+8
lda #>384
sta ControlPort+9
lda #3
ldx #3 ; 3,3 : Save File
jsr appel
lda #<nomgfx
sta ControlPort+4
lda #>nomgfx
sta ControlPort+5
lda #$FF
sta ControlPort+6 ; $FFFF : mémoire graphique
sta ControlPort+7
lda #3
ldx #2 ; 3,2 : Load File
jmp appel
nomgfx: .byte 7
.text "img.gfx"
; 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
gfx: .byte 1, 1, 0, 0 ; en-tête : une tuile
.fill 252
.rept 16 ; 16 lignes : gauche couleur 2, droite couleur 5
.byte $22, $22, $22, $22, $55, $55, $55, $55
.endrept
a: .byte 0
b: .byte 0
t0: .text "Normale : ", 0
t2: .text ", ", 0
t3: .text "retournee : ", 0Normale : 2, retournee : 5