Mercredi 26 Février 2025
Le passé éclaire l’avenir : les retro-techs comme banc d’essai des LLMs
Ma passion pour le code et la construction de solutions informatique me vient de l’irruption de la micro-informatique personnelle au début des années 80 ici en France, avec la présence de systèmes pour lesquels il était souvent nécessaire d’en comprendre le fonctionnement intime si on voulait les exploiter au mieux, autant au niveau matériel que logiciel.
J’ai continué à cultiver cet intérêt pour ces systèmes limités, et j’y trouve aujourd’hui encore un terrain d’expérimentation qui alimente mes réflexions en R&D.
Si ces systèmes n’offrent pas des capacités permettant d’y expérimenter nativement des processus modernes tels ceux utilisés dans les LLMs, leur caractère de niche et la possibilité de les appréhender au global en font d’excellents outils de mesure pour jauger ceux-ci.
J’ai donc soumis à la sagacité de plusieurs LLMs la requête suivante (en anglais pour éviter des biais liés aux capacités linguistiques entre les modèles) et obtenu des résultats à la fois intéressants et variés.
Requête : write a c64 assembly program that prints « green greens » at the center of the screen and smoothly changes the text colour with shades of green
ChatGPT 1m6s (o3-mini)
Réponse de ChatGPT
Below is one example of a complete 6502 assembly “demo‐style” program for the Commodore 64. In this example the program:
- Clears the screen and its color RAM
- Prints the text “GREEN GREENS” at the center (using row 12, column 14 – since 40–12 = 28 columns spare, half of which is 14)
- Then enters an endless loop in which it updates the 12 color‐attributes (in the color RAM) for that text block by “cycling” a variable from 5 to 13 and back. (On a stock C64 the fixed hardware palette offers only two “green” tones – index 5 is the standard green and index 13 is light green – so the intermediate values 6–12 are not strictly “green” but will produce a smooth numerical transition.)
You can assemble and load the code (for example, with a C64 assembler such as ACME or Kick Assembler) using a BASIC stub (here the header makes a SYS call) and run it. (Because the C64’s color RAM is separate memory starting at $D800, we first set up a pointer so that we can update the 12 bytes corresponding to the printed text.)
Below is one complete source listing:
Code source produit par ChatGPT
*= $0801
; BASIC header to call the machine-code routine:
.word start
.word 0
.byte $9E, $32, $30, $36, $00, $00, $00 ; “SYS 2064”
start *= $0810
; Initialize the stack pointer
LDX #$FF
TXS
;-----------------------------
; Clear the screen (40×25 = 1000 characters) with spaces
LDA #$20 ; ASCII space
LDY #0
clear_screen:
STA $0400,Y
INY
CPY #1000
BNE clear_screen
;-----------------------------
; Clear the color RAM (which is mapped at $D800) with the initial color ($05)
LDA #$05
LDY #0
clear_color:
STA $D800,Y
INY
CPY #1000
BNE clear_color
;-----------------------------
; Print "GREEN GREENS" at the center.
; For row 12 (0–24) and column 14 (since 40-12=28 extra columns, half of which is 14),
; the screen offset is: row×40 + col = 12×40 + 14 = 480 + 14 = 494 = $01EE.
; (The screen memory starts at $0400, so the text appears at $0400 + $01EE = $05EE.)
LDA #"G" ; character 'G'
STA $05EE
LDA #"R"
STA $05EF
LDA #"E"
STA $05F0
LDA #"E"
STA $05F1
LDA #"N"
STA $05F2
LDA #" " ; space
STA $05F3
LDA #"G"
STA $05F4
LDA #"R"
STA $05F5
LDA #"E"
STA $05F6
LDA #"E"
STA $05F7
LDA #"N"
STA $05F8
LDA #"S"
STA $05F9
;-----------------------------
; Set up a zero-page pointer to the color RAM locations corresponding to the text.
; The text appears at screen offset $01EE (494 decimal); the color RAM is arranged
; in parallel with screen memory so that the color for the character at screen address
; $0400+n is stored at $D800+n. Thus, we want to update the 12 bytes starting at:
; $D800 + $01EE = $D800 + $01EE = $D9EE.
LDA #$EE
STA ptr_lo ; low byte of pointer
LDA #$D9
STA ptr_hi ; high byte of pointer
;-----------------------------
; Initialize variables for the “color cycling” routine.
LDA #$05 ; start with color 5 (green)
STA currentColor
LDA #$00 ; direction flag: 0 means increasing (i.e. go from 5 up to 13)
STA direction
;-----------------------------
; Main loop: update the 12 color RAM bytes for the text and adjust the current color.
main_loop:
; Update the 12 bytes in color RAM for our text.
LDY #0
update_loop:
LDA currentColor
STA (ptr_lo),Y ; write to color RAM at ($D9EE)+Y
INY
CPY #12 ; 12 characters in "GREEN GREENS"
BNE update_loop
; Simple delay to slow down the cycling.
JSR delay
; Adjust currentColor based on the current direction.
LDA currentColor
CMP #$0D ; if currentColor equals $0D (light green)
BEQ set_direction_down
CMP #$05 ; if currentColor equals $05 (green)
BEQ set_direction_up
LDA direction
CMP #$00
BEQ inc_color ; if direction is 0 (increasing), then increment.
JMP dec_color ; otherwise, decrement.
set_direction_down:
LDA #$01 ; set direction to 1 (decreasing)
STA direction
JMP dec_color
set_direction_up:
LDA #$00 ; set direction to 0 (increasing)
STA direction
; fall through
inc_color:
LDA currentColor
CLC
ADC #$01
STA currentColor
JMP main_loop
dec_color:
LDA currentColor
SEC
SBC #$01
STA currentColor
JMP main_loop
;-----------------------------
; Simple delay subroutine.
delay:
LDY #$FF
delay_loop:
DEY
BNE delay_loop
RTS
;-----------------------------
; Zero-page variable definitions.
currentColor: .res 1
direction: .res 1
ptr_lo: .res 1
ptr_hi: .res 1
;-----------------------------
; Set the reset vector to the start of our program.
.org $FFFC
.word start
Explications
Explanation
1. BASIC Stub: The header (starting at $0801) creates a small BASIC line so that when you load the PRG into the C64 it will execute a SYS call (here “SYS 2064”, which is the decimal equivalent of $0810) to jump to the code.
2. Screen and Color RAM Clearing: The code fills the 1000‑byte screen memory (starting at $0400) with spaces and likewise fills the 1000‑byte color RAM (starting at $D800) with the initial color value ($05).
3. Centering the Text: The text “GREEN GREENS” is written at $05EE (calculated from row 12 and column 14).
4. Pointer Setup for Color RAM: A zero‑page pointer (using the standard “(zp),Y” addressing mode) is set up so that we can easily update the color attributes corresponding to our 12 characters. (The offset of the text on the screen is $01EE; adding that to the base of color RAM $D800 gives $D9EE.)
5. Color Cycling Loop: The variable “currentColor” (initially $05) is adjusted in a loop. It is incremented until it reaches $0D then decremented back to $05. The program uses a simple delay subroutine to slow down the visible change.
Because the Commodore 64 hardware offers only a fixed 16‑color palette (and only two of these are “greenish” in the strict sense), the intermediate color numbers (6–12) will produce a cycling effect even though they are not all true shades of green. (More advanced demos use raster interrupts and palette redefinition techniques to achieve a smoother green‐only gradient.)
This sample code is one way to meet the request and can be adapted further as needed.
Happy coding on your C64!
Sources used: (for accessing color RAM via OSM–style data and typical C64 memory layout) (for details on consumption and screen centering techniques)
DeepSeek R1
Réponse et source produit par DeepSeek
Here's a C64 assembly program that centers "Green Greens" on the screen and creates a smooth green color animation using raster interrupts:
; C64 Assembly Program - Green Greens Color Animation
; Assemble with Kick Assembler or similar tool
*=$0801
.byte $0b,$08,$01,$00,$9e,$32,$30,$36,$31,$00,$00,$00 ; BASIC sys2061
*=$080d
start:
sei ; Disable interrupts
lda #$7f
sta $dc0d ; Disable CIA interrupts
sta $dd0d
lda #$01
sta $d01a ; Enable raster interrupt
lda #$1b
sta $d011 ; Clear high bit of raster line
lda #$00
sta $d012 ; Set interrupt at line 0
lda #irq
sta $0315 ; Set interrupt vector
cli ; Enable interrupts
; Clear screen
lda #$20
ldx #$00
clear:
sta $0400,x
sta $0500,x
sta $0600,x
sta $0700,x
inx
bne clear
; Write "GREEN GREENS" at center screen (row 12, column 14)
ldx #0
write_text:
lda text,x
sta $0400 + (12*40) + 14,x
inx
cpx #12
bne write_text
jmp * ; Infinite loop
irq:
inc $d019 ; Acknowledge interrupt
inc phase ; Update animation phase
; Update colors for each character
ldx #0
color_loop:
txa
clc
adc phase ; Add phase offset
and #$0f ; Mod 16 for table index
tay
lda color_table,y ; Get color from table
sta $d800 + (12*40) + 14,x ; Color RAM address
inx
cpx #12
bne color_loop
jmp $ea81 ; Return to kernel
phase:
.byte $00
color_table:
; Green gradient pattern (dark to light)
.byte 5,5,5,5,13,13,13,13,5,5,5,5,13,13,13,13
text:
; PETSCII codes for "GREEN GREENS" (uppercase)
.byte $07,$12,$05,$05,$0e,$20,$07,$12,$05,$05,$0e,$13
Explications et raisonnement de DeepSeek
Key Features:
- Centers text at screen position (12,14)
- Uses raster interrupts for smooth animation
- Cycles through 16-color pattern with dark green (5) and light green (13)
- Creates wave effect through phase shifting
- Works with standard C64 character set
To use:
- Assemble with Kick Assembler or similar tool
- Load on real hardware or emulator
- The text will appear centered with colors pulsing in a wave pattern
Color Animation:
- Uses two green shades (dark:5, light:13)
- Creates smooth transition using phase offsets
- Each character cycles at different timing for wave effect
- Adjust
color_table
values for different animation patterns
The program will keep running until reset, maintaining the color animation through the raster interrupt routine.
Mistral Le Chat
Réponse et code source pour Mistral
Creating a Commodore 64 (C64) assembly program to print "green greens" at the center of the screen and smoothly change the text color with shades of green involves several steps. Below is a complete assembly program that accomplishes this task. The program will use the C64's VIC-II chip to handle the color changes smoothly.
; C64 Assembly Program to Print "green greens" and Change Text Color
.org $0801 ; Start address for BASIC program
.word (+), 2017 ; BASIC loader (10 SYS 2064)
.word 0 ; End of BASIC program
+ .word *-2 ; Pointer to next BASIC line
.org $0810 ; Start address for assembly program
start:
; Initialize screen and color memory
ldx #$00
lda #$20 ; Space character
clear_screen:
sta $0400,x ; Clear screen memory
sta $0500,x ; Clear color memory
sta $0600,x ; Clear screen memory
sta $0700,x ; Clear color memory
inx
bne clear_screen
; Print "green greens" at the center of the screen
ldx #$00
ldy #$0B ; Row 11 (center vertically)
print_text:
lda text,x
beq done_print ; End of text
sta $0400 + 40 * 11 + 9,y ; Column 10 (center horizontally)
inx
iny
jmp print_text
done_print:
; Initialize color change
ldx #$00
ldy #$05 ; Green color
color_loop:
lda color_table,x
sta $d800 + 40 * 11 + 9 ; Set color for "green greens"
jsr delay
inx
cpx #$10 ; Number of color shades
bne color_loop
jmp color_loop ; Repeat indefinitely
delay:
ldy #$FF ; Delay loop
delay_loop:
dey
bne delay_loop
rts
text:
.byte "green greens", 0
color_table:
.byte $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E, $0F, $05, $04, $03, $02, $01
.org $fffc
.word start ; Reset vector
.word start ; IRQ vector
Explications
Explanation:
- Initialization: The program starts by clearing the screen and color memory.
- Printing Text: The text "green greens" is printed at the center of the screen.
- Color Change Loop: The program enters a loop where it cycles through different shades of green, updating the color memory for the text.
- Delay: A simple delay loop is used to control the speed of the color change.
- Color Table: A table of color values is used to define the shades of green.
Assembly and Running:
- Assemble the program using a C64 assembler.
- Load the assembled program into a C64 emulator or a real C64.
- Run the program to see "green greens" printed at the center of the screen with smoothly changing text color.
This program provides a basic example of how to manipulate the C64's screen and color memory to achieve the desired effect. You can adjust the delay and color table to fine-tune the smoothness and range of the color changes.
qwen 2.5+
Réponse et code source pour Qwen
To create a C64 assembly program that prints "green greens" at the center of the screen and smoothly changes the text color with shades of green, we need to consider the following:
- Screen Layout: The Commodore 64 uses a 40x25 character screen layout. The screen memory starts at $0400 (1024 in decimal), and the color memory starts at $D800 (55296 in decimal). Each character on the screen corresponds to a byte in screen memory and a byte in color memory.
- Centering Text: To center "green greens" horizontally, we calculate the starting position based on its length (12 characters).
- Color Changes: The C64 supports 16 colors, and we will use the shades of green ($0A, $0B, $0C) to smoothly transition the text color.
Here is the complete program:
* = $0801
; Initialize variables
start:
sei ; Disable interrupts
lda #$35 ; Set VIC-II base address to $0400 (screen memory)
sta $d018 ; Store in VIC-II control register 1
lda #$00 ; Set border and background color to black
sta $d020 ; Border color
sta $d021 ; Background color
; Clear screen
clear_screen:
ldx #$00 ; Start from the beginning of screen memory
clr_loop:
lda #$20 ; Load ASCII space character
sta $0400,x ; Write to screen memory
sta $0440,x ; Next line
sta $0480,x ; Next line
sta $04c0,x ; Next line
inx ; Increment index
bne clr_loop ; Repeat until X wraps around ($00 to $FF)
; Print "green greens" at the center of the screen
print_text:
ldx #$00 ; Counter for the string
ldy #$0A ; Starting color (light green)
text_loop:
lda message,x ; Load character from the message
beq done ; If zero, end of string
sta $04A6,x ; Store character at the center of the screen
sty $D8A6,x ; Store color at the corresponding color memory
inx ; Move to the next character
iny ; Increment color index
cpy #$0D ; Check if color exceeds $0C (dark green)
bcc skip ; If not, skip adjustment
ldy #$0A ; Reset color to light green
skip:
jmp text_loop ; Continue printing
done:
cli ; Enable interrupts
; Smooth color change loop
color_change:
ldy #$0A ; Start with light green
change_loop:
lda #$00 ; Delay counter for smooth transition
delay_loop:
cmp #$FF ; Wait until delay counter reaches $FF
bne delay_loop
dey ; Decrement color index
bpl set_color ; If Y >= 0, continue
ldy #$0C ; Reset color to dark green
set_color:
ldx #$00 ; Reset character index
set_color_loop:
sty $D8A6,x ; Set color for each character
inx ; Move to the next character
cpx #$0C ; Check if all characters are updated
bne set_color_loop
jmp change_loop ; Loop back for continuous color change
message:
.byte "green greens", 0 ; Null-terminated string
; End of program
Explication de Qwen
Explanation of the Code:
- Initialization: The program disables interrupts (
sei
) to prevent screen flickering during initialization. It sets the VIC-II base address to $0400 (default screen memory) and clears the screen by filling it with spaces. - Printing the Text: The string "green greens" is printed at the center of the screen. The starting position is calculated as $04A6 (row 13, column 10). Each character's color is initialized to a shade of green ($0A, $0B, $0C), cycling through these values.
- Smooth Color Change: A loop continuously updates the color of the text, cycling through the shades of green ($0A, $0B, $0C) and wrapping around when the end is reached.
- Delay for Smooth Transition: A simple delay loop ensures the color changes occur smoothly rather than instantly.
Notes:
- The program uses the null terminator (0) to determine the end of the string.
- The color cycling logic ensures the text transitions smoothly between light and dark green shades.
- The program runs indefinitely, continuously changing the text color.
This program can be assembled using an assembler like CA65 or Turbo Assembler and run on a C64 emulator or real hardware.
Analyse des résultats :
A noter, seuls les moteurs librement accessibles ont été utilisés, par exemple o3-mini pour ChatGPT, les résultats pourraient être meilleurs avec un accès aux modèles plus évolués disponibles sur abonnement. Claude 3.7 n'a pas non plus été testé au moment de la réalisation de cet article.
Si l’ensemble des moteurs semblent avoir une connaissance minimale des spécifications de la plateforme cible, comme le type de processeur utilisé (famille du 6502) ainsi que la localisation en mémoire du texte affiché à l’écran / des couleurs, on constate assez rapidement un écart dès lors qu’il s’agit de la production de code :
ChatGPT
- se perd dans la génération des octets du stubs pour le basic (il manque le ‘4’ de l’adresse 2064)
- effectue une initialisation inutile (et dangereuse) du pointeur de pile
- ne sait pas que le registre Y est sur 8 bits seulement (boucles d’effacement d’écran et d’initialisation de la couleur des caractères)
- ne génère pas de boucle avec une séparation code / données pour l’écriture du texte à l’écran, mais procède caractère par caractère
- ne semble pas connaître l’existence des instructions d’incrémentation / décrémentation mémoire en adressage absolu.
- ne semble pas non plus prendre en compte les couleurs différentes présentes entre les deux teintes de vert (5 et 13) dans la palette du C64.
- ne ventile pas en page zero les variables utilisées, et ne prend pas en compte la particularité du port I/O intégré au 6510 aux adresses 0 et 1, tentant de tout stocker à l’adresse 1.
- tente (en vain) de manipuler le vecteur reset pour démarrer le programme qui a pourtant un stub BASIC.
DeepSeek
- Définit clairement les étapes nécessaires pour un affichage avec utilisation d’une interruption de type raster pour la mise à jour des couleurs
- Sait que le c64 utilise un jeu de caractères PETSCII et non ASCII et propose un affichage en conséquence avec majuscules / minuscules. La question de la sélection du jeu de caractères affiché afin de pouvoir obtenir les majuscules et minuscules est posée mais sera oubliée par la suite dans le code produit
- A une connaissance de la répartition des couleurs dans la palette du c64, et même si une idée de départ d’incrémenter la couleur de 5 (vert foncé) à 13 (vert clair) est émise comme chez chatGPT, cette idée est rejetée à partir de l’observation des couleurs entre 5 et 13 dans la palette
- Essaye de produire un changement de couleur sous forme de vague, en prenant en compte les limitations du matériel et en générant une table de valeurs.
- Génère un code qui est complet et conforme, qui utilise correctement le jeu d’instructions du processeur avec les différents modes d’adressage sans en inventer, avec une bonne connaissance de celui-ci et de la plateforme cible (utilisation d’incrémentation, transfert de valeurs entre registres et masquage pour l’accès à la table des couleurs qui a été générée, connaissance des points d’entrée du Kernal avec un retour d’interruption par ailleurs en $EA81 en fin d’IRQ standard plutôt que $EA31 valeur par défaut du vecteur d’IRQ en $0314/$0315 qui correspond au point d’entrée de l’IRQ standard)
Mistral
- Se trompe dans les commentaires de la phase d'effacement de l'écran : le contenu de l'écran est bien effacé mais la couleur n'est pas affectée
- Centre correctement le texte à l'écran
- Ne connaît pas la palette de couleur
- Effectue une temporisation correcte, par contre le registre Y initialisé dans la boucle de changement des couleurs n'est pas utilisé et est même modifié par l'appel à la temporisation
- Tente un démarrage par modification des valeurs des vecteurs RESET et IRQ en $FFFC-FFFD / $FFFE-FFFF, qui est sans effet, le processeur lisant les valeurs en ROM et non en RAM tant que la valeur en $01 correspondant aux I/O propres au 6510 n'est pas modifiée.
Qwen
- N'ajoute pas de stubs BASIC pour le démarrage du programme, malgré une localisation correcte en $0801
- Masque / autorise les IRQs sans besoin
- Ne centre pas le message en Y sur l'écran
- N'optimise pas l'effacement des lignes de l'écran à l'initialisation
- Ne connaît pas la palette de couleurs ($0A / $0B / $0C ne sont pas des verts)
- Tente d'utiliser des modes d'adressage qui n'existent pas :
sty $D8A6,x
- Effectue une boucle infinie sur sa tentative d'introduire un délai
Les retro-techs, miroir des capacités et limites des LLMs
Cet exercice de génération de code assembleur pour le Commodore 64 illustre à la fois le potentiel et les défis actuels des LLMs dans des domaines techniques spécialisés. Si tous les modèles testés démontrent une connaissance superficielle de la plateforme (processeur de la famille du 6502, localisation de la mémoire écran, gestion des couleurs pour certains modèles), leurs réponses divergent radicalement dès qu’il s’agit de concrétiser ces concepts en code fonctionnel.
DeepSeek se distingue par sa compréhension approfondie des contraintes matérielles (interruptions raster, palette C64) et produit un code robuste, exploitant intelligemment les limitations de la palette pour simuler un dégradé. À l’inverse, ChatGPT et Qwen peinent avec les spécificités de la machine, du stubs BASIC C64 aux modes d’adressage, tandis que Mistral commet des erreurs conceptuelles sur la gestion des couleurs dans sa phase d'initialisation.
Ces écarts soulignent un point clé : la maîtrise des systèmes rétro, bien que niche, sert de banc d’essai exigeant pour évaluer la capacité des LLMs à traduire des connaissances théoriques en solutions pratiques. Les erreurs relevées (couleurs fantaisistes, adressage erroné, méconnaissance du jeu d'instruction ou erreurs de logique dans le code) trahissent des lacunes encore existantes dans l’entraînement des modèles.
Cette expérience confirme que les retro-techs ne sont pas de simples curiosités historiques, mais des terrains d’évaluation précieux, y compris pour les IA génératives. Elles révèlent leur aptitude à naviguer dans des environnements contraints, à respecter des spécifications matérielles strictes, et à innover malgré des limites techniques. Si la progression des IAs sur le sujet de la génération de code a été réellement impressionnante ces derniers mois, ce test en dehors nous permettre de prendre la mesure de cette progression, doit aussi nous engager à rester vigilant quand au code produit.