Programmation Assembleur

Temps d'accès à la VRAM

Cet article a été mis à jour, vous consultez ici une archive de cet article!

Problématique



Le processeur graphique du MSX (appelé VDP) fonctionne de façon autonome du processeur central (CPU), le Z80.

Le CPU communique avec le VDP à travers des ports d'entrée/sortie (ports I/O).
Ces ports I/O permettent de lire et/ou d'écrire dans les registres qui contrôlent le fonctionnement du VDP (choix du mode graphique, taille des sprites, etc.), mais aussi de lire ou écrire dans la mémoire vidéo (VRAM) du VDP.

La lecture/écriture en VRAM se fait de façon indirect : on configure les registres du VDP (pour indiquer notamment l'adresse à accéder en VRAM), puis on lit/écrit la VRAM à travers les ports I/O.
Le VDP doit traiter ces demandes d'accès de son coté.
Hors, quand il est occupé à afficher une image à l'écran, le VDP peut prendre plus de temps à répondre à ces demandes que de temps qu'il faut au CPU pour les faire.
Il peut donc arriver que le CPU envois des données trop rapidement au VDP et que certaines soient perdues, faute de temps pour les traiter.
Il en résulte un affichage incorrect des données que le programme souhaitait envoyer.
Idem si le CPU essaye de lire trop vite des données en VRAM : Les valeurs récupérées peuvent être incorrectes.

Le temps de traitements des demandes d'accès à la VRAM dépend de certains paramètres :
- La génération du VDP,
- Le mode écran (screen mode) actuel,
- L'activité du VDP au moment de la demande.

Génération et mode écran



Durant la période commerciale du MSX, 3 générations de VDP ont été utilisés :
- Texas Instrument TMS9918 (MSX1),
- Yamaha V9938 (MSX2),
- Yamaha V9958 (MSX2+ et turbo R).

Voici les temps d'accès minimal au VDP exprimé en nombre de cycles du CPU en fonction des modes écrans.
Screen mode VDP mode MSX1 cycles MSX2/2+ cycles
0,W40 T1 12 20
0,W80 T2 -- 20
1 G1 29 15
2 G2 29 15
3 MC 13 15
4 G3 -- 15
5 G4 -- 15
6 G5 -- 15
7 G3 -- 15
8 G7 -- 15

Globalement, le V9938 est plus rapide que le TMS9918... a une exception près.

Activité du VDP



L'activité du VDP au moment de la demande à un gros impact sur son temps de réaction.
Par exemple, lorsque le VDP est en train de "dessiner" les bordures, son temps de réaction est plus grand que le temps minimum nécessaire pour le CPU pour faire une demande d'accès à la VRAM.
Ainsi, dans certains cas, il n'y a aucun contrainte de temps d'accès à la VRAM :
- Quand le VDP est dans le H-Blank (bordure droite/gauche), ou le V-Blank (bordure bas/haut). Note : Le V-Blank étant relativement long, il est possible d'utiliser ce temps pour lire/écrire des données en VRAM a une vitesse maximale.
- Quand l'affichage est désactiver. Note : On peut utiliser un écran noir (affichage désactivé) pour charger plus rapidement un niveau par ex.

L'activation ou non des sprites a un impact sur la réactivité du VDP, mais l'impact exacte sur les temps d'accès n'est pas connu.

Accès au VDP en assembleur



Le CPU communiquant avec le VDP via les ports I/O, ce sont les instructions in et out (et leurs dérivés) qui sont utilisés.

Dans la suite de ce chapitre, nous n'allons aborder que les accès en écriture de la VRAM (cas le plus fréquent), mais toutes les contraintes décrites ci-dessous s'applique exactement de la même façon pour la lecture en VRAM.

Remplissage



Après la configuration des registres pour accéder à la VRAM de façon séquentielle (qui n'est pas expliqué ici), le moyen le plus rapide d'écrire 4 octets en VRAM est :

; Ecrire la valeur de A dans 4 octets consécutif en VRAM
out (0x98), a
out (0x98), a
out (0x98), a
out (0x98), a


L'instruction out (n),a prenant 12 cycles sur MSX, elle est trop rapide pour la plus part des modes d'affichage (en dehors du V-Blank).

L'instruction out (c),a (ou le numéro de port I/O se trouve dans le registre C) prend elle 14 cycles sur MSX. Ce qui est un chouilla trop rapide pour la plupart des modes d'affichage. Ajouter un nop entre chaque out (c),a permet d'arriver à 15 cycles, l'intervalle minimale d'accès à la VRAM des modes bitmap du MSX2 (comme le Screen 5 par ex.).

Par contre, cette solution est encore trop rapide pour les modes graphiques du MSX1 (29 cycles) ou les modes textes du MSX2 (20 cycles). Dans ces cas, le mieux est d'intercaler d'autres instructions entre les out pour les écarter suffisamment dans le temps, sans perdre du temps CPU à ne rien faire avec une longue série de nop .

Copie



Les exemples précédent ne permettent que de remplir une zone de VRAM avec une valeur unique. C'est utile pour effacer une zone de VRAM par ex., mais la plus part du temps, le programme va vouloir envoyer des données graphiques qui viennent de la mémoire du CPU (un image, un sprite, etc.) et il faut donc utiliser les instructions Z80 qui le permettent ( ini par ex.).