Assembleur 6502 - VCS2600

Cette catégorie traite de développements récents pour nos vieilles machines, applications, jeux ou démos... Amis programmeurs, c'est ici que vous pourrez enfin devenir célèbres!

Modérateurs : Papy.G, fneck, Carl

Avatar du membre
Falkor
Messages : 1271
Enregistré le : 28 juin 2010 12:09
Localisation : Cluny, Saône et Loire

Assembleur 6502 - VCS2600

Message par Falkor » 13 avr. 2020 10:16

Salut à tous,

Profitant encore et toujours de ces (longs ?) moments pour faire de la théorie, j'avais envie de pousser davantage mes faibles connaissances en assembleur et de m'intéresser davantage à une console que j'aime bien, l'Atari 2600. En quelques lignes d'assembleur, il est plus ou moins facile d'obtenir rapidement des graphismes. :P

J'ai commencé par parcourir l'excellent tuto disponible ici :

https://www.randomterrain.com/atari-260 ... ie-01.html

Qui explique vraiment très bien la génération d'image, les timings, les bases de l'assembleur... Et qui propose des exemples pas à pas. Il ne semble toutefois pas aller jusqu'au bout des possibilités de la machines (sprites, collisions, joysticks...), il faudra donc que je cherche d'autres sources d'infos.

Pour l'édition/assemblage du code j'utilise l'IDE en ligne 8bitworkshop dont quelqu'un avait fait la pub il y a quelques temps :

https://8bitworkshop.com/v3.5.1/?file=e ... atform=vcs# (qui contient également quelques exemples)

J'ajoute à ces éléments le jeu d'instructions du 6502 : https://www.atariarchives.org/2bml/chapter_10.php

Et en complément le "Stella programming guide" qui est très complet mais qui manque peut-être un peu de pédagogie. :roll:

J'ai commencé par étudier la méthodologie de tracé d'un "fond". Sur la VCS l'arrière plan est constitué de deux éléments : un arrière plan coloré (une seule couleur par "scanline") et d'un "playfield" constitué de trois registres qui vont permettre de tracer la moitié gauche de l'écran. Pour la seconde moitié, on peut soit re-dessiner un autre "playfield" différent du premier, soit répéter celui de gauche, avec ou sans symétrie.

Pour chaque "scanline", il est donc nécessaire de définir la couleur d'arrière plan, la couleur du "playfield", et les trois registres permettant de décrire la géométrie de ce dernier. Le bleu et le vert foncé sont des variations de couleur de l'arrière plan, le blanc et les arbres sont le "playfield" coloré.

En bricolant un peu et en automatisant la lecture de pixels à partir d'une image, j'ai pu obtenir ceci :
exemple.png
exemple.png (122.27 Kio) Vu 994 fois
En utilisant donc la symétrie pour obtenir le "playfield" de droite.

Bon une fois cette étape passée, je souhaite ajouter un personnage pouvant bouger. Mais c'est là que les soucis arrivent... Mon code est très mal fait !

Suite au prochain épisode !

PS : Des dieux de l'assembleur 6502 ici ?? Je vais avoir besoin d'aide :lol:

Avatar du membre
snsv6502
Messages : 92
Enregistré le : 12 oct. 2018 21:28
Localisation : Nantes

Re: Assembleur 6502 - VCS2600

Message par snsv6502 » 13 avr. 2020 13:27

Ne connaissant rien au VCS2600, je n'ai rien compris, mais un grand merci pour l'adresse "8bitworkshop.com", je ne connaissais pas et c'est tout simplement g.é.n.i.a.l !
On peut bidouiller sur apple ][ à la volée, surpuissant ! :mrgreen:
call-151

Avatar du membre
6502man
Messages : 10184
Enregistré le : 12 avr. 2007 22:46
Localisation : VAR
Contact :

Re: Assembleur 6502 - VCS2600

Message par 6502man » 13 avr. 2020 20:21

Tu n'as pas pris la machine la plus facile pour commencer en 6502 :lol: :lol:

Bon déjà tu as compris le plus complexe c'est à dires qu'il faut dessiner ligne par ligne l'image et idem pour les sprites :lol: :lol: :lol:

J'avais fait quelques trucs il y a plus de 15 ans sur VCS2600 :shock: hou la vache ça rajeuni pas :?

Dans le principe tu dois dessiner à chaque raster background, playfield, sprite joueur, missile donc tu dois savoir selon où est le raster si tu dois envoyer telles ou telles données (de mémoire ça devrait être ça).
C'est assez sportif mais avec l’émulateur ça aide bien à comprendre ce qu'il faut écrire comme données au bon moment :wink:

Après la partie 6502 si tu as besoin d'aide je devrais pouvoir t'aider :D
Phil.

www.6502man.com

To bit or not to bit.
1 or 0.

Avatar du membre
Falkor
Messages : 1271
Enregistré le : 28 juin 2010 12:09
Localisation : Cluny, Saône et Loire

Re: Assembleur 6502 - VCS2600

Message par Falkor » 14 avr. 2020 08:21

Voici comment l'image montrée dans mon premier post à été générée. Dans la boucle principale d'affichage de l'image en cours j'ai simplement codé plein de boucles identiques comme celle-ci :

Code : Tout sélectionner

    
PictureLoop1 
           ;Init playfield patterns for ONE or more scanline
           lda  #%01100000
           sta PF0      
           lda #%01100000
           sta PF1
           lda #%11111110
           sta PF2       ; PF0, PF1 et PF2 sont les registres du "playfield"                 
           sta WSYNC    ; attente scanline
           inx    ; le registre X représente la scanline en cours, je l'incrémente
           cpx #54  ; on compare la valeur de X à 54
           bne PictureLoop1  ; boucle X fois sur la même scanline pour répéter le dessin 
Et aux endroits qui vont bien, je modifie les registres de couleurs :

Code : Tout sélectionner

lda #$9A ;couleur BLEUE           
sta COLUBK  ; sav couleur registre d'ARRIERE PLAN
Bref ce code fonctionne mais n'est absolument pas optimisé. Pour ajouter des sprites à l'écran je dois écrire dans des registres pile à la scanline désirée, et mon monstrueux code ne le permet pas.

En lisant d'autres extraits du tuto , l'auteur conseille de travailler avec des tables contenant les octets des différents registres, puis de faire une boucle unique d'appel de ces valeurs via un "Zero-Page Addressing" (pas sûr de la traduction), ce qui donne quelque chose comme ceci :

Code : Tout sélectionner

    ldx #0   ;2        
Kernel lda PF0Table,x   ;4
    sta PF0   ;3
    lda PF1Table,x   ;4
    sta PF1   ;3
    lda PF2Table,x   ;4
    sta PF2   ;3
    sta WSYNC   ;3
    inx   ;2    
    cpx #192    
    bne Kernel   ;3(2)
On charge donc dans X la valeur 0, valeur utilisée pour aller lire respectivement les tables de valeurs PF0Table à PF2Table. Chaque valeur est ensuite envoyée dans les registres qui vont bien (PF0 à PF2).

Le registre X est incrémenté, comparé à 192, et si pas encore égal à 192 on boucle. (192 étant le total de scanlines pour une image !)

Et en fin de code j'ai mes tables correspondant aux valeurs de PF0, PF1 et PF2 :

Code : Tout sélectionner

PF0Table  ; table 0  
        .byte  #%10000000,
        .byte  #%10000000,
        .byte  #%10000000,n
        .byte  #%11000000,
(...)
(Bon en binaire pour le moment, ça me parle mieux. :roll: )

Je comprends la logique du code , mais patatras sur émulateur ça ne fonctionne pas :
erreur.png
erreur.png (18.97 Kio) Vu 884 fois


Le système semble bien aller chercher mes valeurs et trace le décor, mais une scanline sur deux semble être complètement vide, comme si 0 était attribué à mes registres d'arrière plan. Et là... Je ne comprends pas du tout. :cry:

J'ai calé FF dans toutes les tables pour vérifier, j'ai toujours le souci.

Ne pouvant à priori pas faire de débuggage, je suis incapable de vérifier la valeur de X dans ma boucle. On à l'impression qu'un double appel à sta WSYNC est fait, mais je ne sais pas où...

Avatar du membre
6502man
Messages : 10184
Enregistré le : 12 avr. 2007 22:46
Localisation : VAR
Contact :

Re: Assembleur 6502 - VCS2600

Message par 6502man » 14 avr. 2020 12:10

Ne pouvant à priori pas faire de débuggage, je suis incapable de vérifier la valeur de X dans ma boucle........
Si si tu peux faire du deboggague avec l’émulateur en ligne sur 8bitworkshop.

exemple pendant l’exécution de ton code tu appuie sur pause ou single step et en bas à droite tu à une petite fenêtre qui apparait avec
la valeurs de registres tu peux choisir TIA pour avoir la valeur des registres graphiques.
Ensuite tu peux soit faire du pas à pas et voir l'évolution des divers registres CPU TIA ou autres.
Tu peux aussi mettre des point d’arrêt (breakpoint) dans le code ou tu veux et exécuter jusqu'au point d’arrêt ....

Pour finir ta parti de code n'utilise pas la page zéro :roll: ???
Phil.

www.6502man.com

To bit or not to bit.
1 or 0.

Avatar du membre
Falkor
Messages : 1271
Enregistré le : 28 juin 2010 12:09
Localisation : Cluny, Saône et Loire

Re: Assembleur 6502 - VCS2600

Message par Falkor » 14 avr. 2020 13:18

Ah ok si je peux mettre des points d'arrêt c'est cool, je n'avais pas remarqué. Je vais tenter ça !

Pas de page zéro ? Ce n 'est pas ce type de notation la page zéro ?

Code : Tout sélectionner

PF0Table,x   
sta PF0  
EDIT : je suis en train de faire du débuggage et effectivement il y a remise à zéro des registres du TIA une ligne sur deux...

Le "x" de "PF0Table,x" ne correspond pas direct à la valeur du registre du même nom :?:

Avatar du membre
rendomizer
Messages : 302
Enregistré le : 17 juin 2016 21:00
Contact :

Re: Assembleur 6502 - VCS2600

Message par rendomizer » 14 avr. 2020 16:14

c'est facinant de beauté ! mais pourquoi ce choix de la vcs 2600 plutot que le vg5000 par exemple et le z80 tu aurais plus d'aides ! :P
le mot de passe c'est quoi ? quoi.

Avatar du membre
6502man
Messages : 10184
Enregistré le : 12 avr. 2007 22:46
Localisation : VAR
Contact :

Re: Assembleur 6502 - VCS2600

Message par 6502man » 14 avr. 2020 16:56

@Flakor: le X est un index absolument pas la valeur lue :shock:

dans cette exemple : lda PF0Table,x
L'accumulateur recoit la valeur de la case mémoire PF0Table + X
Si X= $04 et PF0Table = $70 tu lira la case mémoire $74
Cela permet de parcourir une zone en incrémentant seulement l'index dans le cas présent X mais on est limité à $FF.

Pour utiliser l'adresse par la page zéro il y à plusieurs façon de procéder même si la ligne précedent en fait parti, mais ca dépend surtout et beaucoup des contraintes de mémoire que tu à, et surtout tu devrais commencer par une initiation à l'assembleur 6502 c'est la base pour aller plus loin :D

L'adressage le plus puissant si tu à besoin d’accéder à plus de $FF données et surtout si c'est données ne sont pas "caler" c'est l'adressage indexé par Y du type LDA ($xx),Y un peu compliqué au premier abord mais c'est très puissant :D
Modifié en dernier par 6502man le 14 avr. 2020 17:21, modifié 1 fois.
Phil.

www.6502man.com

To bit or not to bit.
1 or 0.

Avatar du membre
Falkor
Messages : 1271
Enregistré le : 28 juin 2010 12:09
Localisation : Cluny, Saône et Loire

Re: Assembleur 6502 - VCS2600

Message par Falkor » 14 avr. 2020 17:05

rendomizer a écrit :
14 avr. 2020 16:14
mais pourquoi ce choix de la vcs 2600 plutot que le vg5000 par exemple et le z80 tu aurais plus d'aides ! :P
Disons que la VCS2600 est ma première console, que j'ai toujours, et qui me semble être une machine très intéressante à étudier. Je suis moins familier avec le VG5000, mais ça viendra surement un jour...!

6502man a écrit :
14 avr. 2020 16:56
dans cette exemple : lda PF0Table,x
L'accumulateur recoit la valeur de la case mémoire PF0Table + X
Si X= $04 et PF0Table = $70 tu lira la case mémoire $74
Cela permet de parcourir une zone en incrémentant seulement l'index dans le cas présent X mais on est limité à $FF.
Donc là OK. Pas grave non plus si l'index ne peut aller que jusqu'à $FF, ma table est moins longue que ça.

Mais quand je lis ça :
Zero Page,X

The address to be accessed by an instruction using indexed zero page addressing is calculated by taking the 8 bit zero page address from the instruction and adding the current value of the X register to it. For example if the X register contains $0F and the instruction LDA $80,X is executed then the accumulator will be loaded from $008F (e.g. $80 + $0F => $8F).
Je vois pas pourquoi ça fonctionne pas ? Dans mon cas je veux justement qu'il aille mettre dans l'accumulateur l'octet situé à l'adresse "PF1Table + la valeur de X" ? (Et c'est ce qu'il tente à peu près de faire...)

Avatar du membre
6502man
Messages : 10184
Enregistré le : 12 avr. 2007 22:46
Localisation : VAR
Contact :

Re: Assembleur 6502 - VCS2600

Message par 6502man » 14 avr. 2020 17:24

J'ai pas tout le code sous les yeux pour vérifier !

Donc ta table est déjà en page zéro ?
Phil.

www.6502man.com

To bit or not to bit.
1 or 0.

Avatar du membre
Falkor
Messages : 1271
Enregistré le : 28 juin 2010 12:09
Localisation : Cluny, Saône et Loire

Re: Assembleur 6502 - VCS2600

Message par Falkor » 14 avr. 2020 17:47

Alors ma table (la première) est à $F091 (cf le code assemblé).

Je suis en train de lire des choses sur la page zéro. En attendant, si tu veux jeter un oeil, le code est en PJ.

Merci de ton aide ! :)
problem.zip
(2.15 Kio) Téléchargé 22 fois

Avatar du membre
snsv6502
Messages : 92
Enregistré le : 12 oct. 2018 21:28
Localisation : Nantes

Re: Assembleur 6502 - VCS2600

Message par snsv6502 » 14 avr. 2020 17:57

Euh, ton histoire de page zéro, c'est peut-être un souci du compilateur en ligne, il faudrait voir quel est le code hexa résultant, non ?
Par exemple :
LDA $05 devrait donner : A5 05 ... mais si ton compilateur est un peu neuneu, il peut donner ça : AD 05 00 (sous entendu LDA $0005), un gugus dans mon genre s'en moquerait bien vu qu'au final l'accumulateur récupère le contenu de l'adresse $05 mais en nombre de cycles, c'est plus du tout pareil donc si c'est un truc un peu chatouilleux de ce style pour lequel une microseconde c'est vachement important et ça peut tout changer... :? il faudrait vérifier le code généré, sait-on jamais.
:wink:
Pourrais-tu mettre un lien vers ton code dans l'interface ou copier / coller ton code source complet stp ?
call-151

Avatar du membre
Falkor
Messages : 1271
Enregistré le : 28 juin 2010 12:09
Localisation : Cluny, Saône et Loire

Re: Assembleur 6502 - VCS2600

Message par Falkor » 14 avr. 2020 18:29

Je n'ai pas encore regardé le code assemblé. Je vais aussi tenter d'assembler ma source avec DASM qui est apparemment la référence.

La source est dans mon dernier message si tu veux jeter un œil !

Je me documente pendant ce temps sur tout ces modes d'adressage...

Merci de votre aide !

Avatar du membre
snsv6502
Messages : 92
Enregistré le : 12 oct. 2018 21:28
Localisation : Nantes

Re: Assembleur 6502 - VCS2600

Message par snsv6502 » 14 avr. 2020 19:01

Ah oui, désolé j'avais loupé le code source :mrgreen:
L'accès en page zero est plus rapide donc je suppose que c'est pour ça qu'il faut utiliser la PZ... mais comme je l'ai dit je ne connais rien au VCS2600, rien à l'architecture, rien de rien, alors c'est juste une supposition.
La PZ pour un 6502, c'est bien utile pour l'adressage direct PZ plus rapide, l'indexé PZ plus rapide aussi (pas sûr ma mémoire me fait défaut) mais aussi pour l'indirect indexé ou l'indexé indirect (seul moyen de le faire)... bref, ça vaut le coup de potasser et se demander pourquoi il faut que ton code bidouille en PZ.
Je vais tenter une incursion dans l'architecture de l'atari 2600 pour essayer de comprendre, après tout je bavais devant cette machine quand j'étais gamin... j'ai oublié pourquoi :lol:

PS : ben non, c'est compilé proprement, donc j'ai tout faux. :? :oops:
Même pas grave, allons essayer de comprendre comment ça marche ce bazar :mrgreen:

pps : Bon, j'ai bidouillé un peu le code pour virer la ligne à moitié remplie du dessus... ça sert à rien mais c'est cool.
D'autre part, selon l'environnement de développement, il passe automatiquement en mode NTSC, qui est sauf erreur un format entrelacé et, même sans rien comprendre au VCS 2600, c'est peut-être un indice ?
:?
ppps : Sinon y'a une partie des datas de l'image qui n'est pas affichée, je l'ai bricolée et ça n'a pas d'incidence sur l'affichage, on peut peut-être creuser de ce côté là ?
Je dis ça d'instinct sans rien connaître à la machine, demain sera une journée à potasser la doc de cette console et on verra si j'y comprends quelque chose :mrgreen:
Tu veux pas coder sur apple ][ plutôt ?... nan je déconne ça a l'air rigolo l'atari 2600 8)

Le code bidouillé :
https://we.tl/t-2LYt4uWQwf
call-151

Avatar du membre
Falkor
Messages : 1271
Enregistré le : 28 juin 2010 12:09
Localisation : Cluny, Saône et Loire

Re: Assembleur 6502 - VCS2600

Message par Falkor » 14 avr. 2020 20:21

Pour faire avancer le schmilblik, voici la memory map de la bête :

Code : Tout sélectionner

registres TIA   $0000 à $007F
RAM		$0080 à $00FF
registres RIOT	$0200 à $02FF
ROM		$1000 à $1FFF
Décimal:

Code : Tout sélectionner

registres TIA   0 à 127
RAM		128 à 255
registres RIOT	512 à 767
ROM		4096 à 8191

J'avoue ne pas tout comprendre dans les explications des modes d'adressage :
L'adressage en page zéro :

La zone composée des 256 premiers octets est appelée la page zéro (sur 16 bits, la partie haute est toujours égale à 0). Plutôt que d'indiquer cette partie haute toujours à 0, il existe des instructions qui travaillent directement dans cette page. Ceci permettant de gagner en taille occupée (au lieu de 3 octets, 1 pour l'instruction et 2 pour la zone mémoire, on occupe 2 octets : 1 pour les instructions et 1 pour la zone mémoire) et donc un gain en vitesse d'exécution.

Syntaxe : Instruction valeur où valeur < 256

L'adressage en page zéro indexé :

La valeur indiquée est une adresse comme origine, le nombre qui est stocké dans le registre X sera ajouté à la valeur de l'adresse d'origine. L'adresse finale sera donc égale à la valeur de l'adresse d'origine + la valeur du registre X.

Syntaxe : Instruction valeur,X où valeur est < 256.
Quand on parle des "premiers 256 octets" on parle desquels ? Du bus d'adresse ? Ma rom démarre à $1000, donc pas forcément possible d'avoir mes données dans les 256 premiers octets...

EDIT : C'est bon je pense avoir compris le fonctionnement du mode. Dans le cas d'un adressage absolu les deux octets présents après l'opcode concernée (genre LDA) représentent donc l'adresse mémoire à charger (attention, octet de poids faible en premier !!).

Dans la cas de la page zéro (c'est à dire le poids fort = 0), donc dans les 256 premiers octets disponibles, et pour accélérer le traitement, une autre instruction ne prenant qu'un octet de donnée d'adresse permet d'accéder plus rapidement à ces premiers 256 octets.

J'en veut pour preuve :

lda $02 s'assemble en A5 02
lda $100 en AD 00 01

Cohérent vis à vis de jeu d'instructions :

Code : Tout sélectionner

LDA  Load Accumulator with Memory

     M -> A                           N Z C I D V
                                      + + - - - -

     addressing    assembler    opc  bytes  cyles
     --------------------------------------------
     immidiate     LDA #oper     A9    2     2
     zeropage      LDA oper      A5    2     3
     zeropage,X    LDA oper,X    B5    2     4
     absolute      LDA oper      AD    3     4
     absolute,X    LDA oper,X    BD    3     4*
     absolute,Y    LDA oper,Y    B9    3     4*
     (indirect,X)  LDA (oper,X)  A1    2     6
     (indirect),Y  LDA (oper),Y  B1    2     5*

Je regarde ton code !

Répondre