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:

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:

  1. Centers text at screen position (12,14)
  2. Uses raster interrupts for smooth animation
  3. Cycles through 16-color pattern with dark green (5) and light green (13)
  4. Creates wave effect through phase shifting
  5. Works with standard C64 character set

To use:

  1. Assemble with Kick Assembler or similar tool
  2. Load on real hardware or emulator
  3. The text will appear centered with colors pulsing in a wave pattern

Color Animation:

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:

  1. Initialization: The program starts by clearing the screen and color memory.
  2. Printing Text: The text "green greens" is printed at the center of the screen.
  3. Color Change Loop: The program enters a loop where it cycles through different shades of green, updating the color memory for the text.
  4. Delay: A simple delay loop is used to control the speed of the color change.
  5. Color Table: A table of color values is used to define the shades of green.

Assembly and Running:

  1. Assemble the program using a C64 assembler.
  2. Load the assembled program into a C64 emulator or a real C64.
  3. 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:

  1. 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.
  2. Centering Text: To center "green greens" horizontally, we calculate the starting position based on its length (12 characters).
  3. 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:

  1. 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.
  2. 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.
  3. 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.
  4. Delay for Smooth Transition: A simple delay loop ensures the color changes occur smoothly rather than instantly.

Notes:

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

DeepSeek

Mistral

Qwen

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.