ASMtrad CPC

Apprenez l'assembleur Z80

Les ROMs - Fonctionnement et structure.

Les ROMs sont pour le cpc l'un des nombreux moyens de stocker des programmes.
Le CPC old peut gérer 255 ROMS (nous verrons plus loin que c'est un peu différent sur cpc+).

Les Types de ROMs:

Ce chapitre va être assez court, puisque seuls 2 types de ROMs existent: Les ROMS BASSES et les ROMS HAUTES.

- Les ROMS BASSES sont des ROMS qui se connectent en mémoire basse. Comprendre par mémoire basse: en dessous de #C000.

Sur CPC old vous n'aurez pas le choix de l'adresse et ces ROMs se connecteront uniquement entre #0000 et #3FFF (16Ko).

Sur CPC+ le choix sera possible entre: #0000/#3FFF ; #4000/#7FFF ; #8000/#BFFF

Sur CPC old, seules deux ROMS BASSES sont connues: LE FIRMWARE et LA MULTIFACE II.

- Les ROMS HAUTES se connectent entre #C000/#FFFF.
La totalité des ROMs d'extension connues sont des ROMs hautes.

ROMs de Premier et second plan:

Il existe deux genre de ROMs: Les ROMs de premier plan et les ROMs de second plan.

Les ROMs de 1er plan prennent la main directement.
Pas d'initialisation au sens propre, dès qu'une telle ROM est connectée, le Firmware lui donne la main.
C'est typiquement le cas du BASIC.
Autre ROM connue: LE HACKER.

Les ROMS de 2nd plan ne font rien de particulier.
Lorsqu'elles sont détectées:
- Le firmware place leurs RSXs en RAM (on verra cela plus loin). - Un jp est exécuté sur la première adresse fournie (là aussi on verra cela plus loin). - La main est rendue et les ROMs suivantes sont initialisées.

L'initialisation des ROMs se fait du haut vers le bas.
Ainsi une ROM de numéro inférieur sera initialisé APRÈS un numéro supérieur (La ROM 6 est initialisée avant la ROM 5, elle même initialisée avant la ROM 4...).

Initialisation des ROMs:

Au démarrage de votre CPC, le Firmware va initialiser les ROMS.
Mais pas toutes, celui-ci ne regardera que les ROMS ayant pour numéro 0 à 15.

Les autres ne seront initialisées sauf s'il s'agit de ROMs de premier plan.

Pour les ROMs de premier plan avec un numéro supérieur à 15, elle ne seront initialisées que s'il n'y a pas de ROM libre entre deux.
Par exemple, si vous ajoutez des ROMs 16 17 18 et 24; et que votre ROM de premier plan est en 18 elle sera detectée.
En revanche si vous la mettez en 24 elle ne sera pas detectée car la ROM 23 n'existe pas.

Attention cependant à un détail: Le Firmware des 464 lui n'initialisera QUE les ROMs de second plan de numéro 0 à 7 !!!
Un changement de la ROM Firmware vers une version supérieure règle le problème.

De même notez bien que le Firmware n’initialise QUE LES ROMS DE SECOND PLAN !!!
Et c'est bien logique puisque les ROMs de premier plan prenants la main il n'y a rien à initialiser.

Notez aussi que l'initialisation des ROMs se fait une fois la main donnée à la ROM 0.
Sur cpc en cas normal il s'agit du BASIC.
Celui-ci est donc initialisé et c'est ensuite que les ROMs le sont.

Pour chaque ROM en commençant par la 15 et en descendant jusqu'à la 0, le Firmware placera les vecteurs d'indirection et les RSX en RAM.
Plus il y a de RSX, plus cela prendra donc de place.

Comme les ROMs sont initialisées du haut vers les bas, si deux ROMs possèdent un RSX avec le même nom, c'est celui de la ROM la plus basse qui sera prioritaire.

De même si un logiciel en ROM utilise plusieurs ROMs et que l'une d'elle doit détecter la présence de l'autre, vous avez tout intérêt à ce que la ROM à détecter ait été placée plus haut.

Structure d'une ROM.

La structure est simple et je vous la donne directement avant de donner plus de détails:

#C000: Type (0 ou 1)
#C001: Mark Number
#C002: Version Number
#C003: Modification Level
#C004: Adresse de la table des noms de vos RSXs
#C006/...: JP vers RSX

Le Type correspond au Type de ROM.
Si =0 alors c'est une ROM de premier plan.
Si =1 alors c'est une ROM de second plan.
Seuls les deux premiers bits de poids faible sont significatifs.
Aussi vous en convenez, on pourrait donc mettre 2 ou 3... Sauf que votre ROM sera ignorée et considérée comme externe au cpc.
Le bit 7 lui doit impérativement être à 0. Ce bit à 1 est réservé pour la ROM interne du cpc.
Les bits 2 3 4 5 et 6 sont ignorés.
En conclusion, n'utilisez comme valeur que 0 ou 1.

Mark Number; Version Number et Modification level: Pour donner un numéro de version à votre ROM.

Adresse de la table des noms de vos RSX sur 2 octets (puisque c'est une adresse), vous mettrez ici l'adresse ou trouver la table des noms des RSX.
Cette table des noms peut contenir autant de RSX que vous le souhaitez. Je la décris un peu plus loin.

JP vers RSX:
Pour chaque nom de RSX, vous devrez donner un JP vers la routine correspondante.
Par exemple vous avez créé un RSX "BIDULE".
Votre routine se trouve en #C820 dans la ROM, vous devrez donc mettre dans la table des JP: JP #C820. L'instruction JP doit être présente.
Les JP doivent êtres mis dans l'ordre des noms que vous avez donné.

Table des noms des RSX:

Comme nous l'avons vu au dessus, en #C004 vous donnez les deux octets de l'adresse de votre table contenant les noms des RSX.
Cependant, reste à vous donner la structure de ces noms.

Tout d'abord, les noms sont illimités.
Il n'y a pas de limite et vous pouvez créer autant de RSX que vous le souhaitez.

Les noms sont en revanche limités à 16 caractères.

Les noms doivent être écrits en MAJUSCULES !!! Sinon le RSX ne sera pas appelable depuis le BASIC.
Il en est de même s'il contient un caractère "espace" ou d'autres caractères non alphanumériques.

Chaque nom doit se terminer avec le bit 7 à 1 afin de détecter la fin de celui-ci.
Pour un RSX nommé "RSX TEST", vous pourrez assembler: DB "TES","T"+#80

La table doit obligatoirement se terminer par un 0 !!!

Vous êtes obligé d'avoir une entrée minimum dans votre ROM.
C'est à dire 1 nom et 1 JP.
Si il s'agit d'une ROM de second plan, le JP sera effectué à l'initialisation.

Afin que cela soit plus clair, voici un exemple d'entête de ROM:

                        ORG         #C000,#4000
                        NOLIST
                        DB          1                       ;ROM DE 2ND PLAN
                        DB          0                       ;MARK NUMBER
                        DB          0                       ;VERSION
                        DB          2                       ;MODIFICATION LEVEL
                        DW          LESNOMS                 ;ADRESSE DES NOMS DES RSX
                        JP          INFO                    ;première RSX qui sera lancée directement à l'initialisation
                        JP          RSX1
                        JP          RSX2
                        JP          RSX3
                        JP          RSX4
                        JP          RSX5
            LESNOMS     DB          "BEST RO","M"+#80       ;nom de la première RSX qui correspond aussi au nom de la ROM
                        DB          "RSX","1"+#80           ;nom du RSX1
                        DB          "RSX","2"+#80           ;nom du RSX2
                        DB          "RSX","3"+#80
                        DB          "RSX","4"+#80
                        DB          "RSX","5"+#80
                        DB          0                       ;fin de la table des noms

Passage de paramètres vers les RSX:

Vous voulez créer une RSX qui demande à ce que des paramètres soient donnés en entrée. Mais comment faire ?

Imaginons un RSX de type: ùraster,encre,couleur1,couleur2

Lorsque vous entrerez vos paramètres, le registre A sera augmenté à chacun de ceux-ci.
Ainsi dans le cas présent, nous avons 3 paramètres (encre, couleur1,couleur2).
A sera donc égal à 3.

Les valeurs de ses paramètres entrés sont stockés dans une table. L'adresse du dernier octet de cette table est stocké dans IX.
Ainsi IX pointera sur la valeur "couleur2".
Il suffira ensuite de decrementer IX pour passer a la valeur "couleur1" puis "encre"