La mémoire vive des Amstrad CPC

T&J du GPA (c) 13/08/2000 * Maj du 25/06/07 !


Voici un petit topo sur la mémoire vive de la famille des Amstrad CPC. Si le sujet peut sembler un peu simplet, il est de fait quasiment impossible de trouver un article ou un livre traitant du sujet globalement. C'est du moins ce que je pensais jusqu'à ce que je tombe sur un article similaire de l'ami Madram dans Amslive. Même si pas mal d'informations sont redondantes (nous parlons de la même machine !), je pense que cette bafouille est quand même intéressante et complémentaire de celui de notre fugueur national !


I CPC464 = 64ko !

Comme son nom l'indique, l'Amstrad CPC 464 est un ordinateur disposant nativement de 64ko, soit 65536 octets. Cette mémoire est organisée en quatre blocs de 16ko chacuns, que nous allons nommer blocs r0,r1,r2,r3. Cette notation n'a aucune légitimité technique, mais cela nous permettra de nous y retrouver plus facilement par la suite :

BlocZone mémoire (hexa)Zone mémoire (décimal)
r0&0000-&3FFF00000-16383
r1&4000-&7FFF16384-32767
r2&8000-&BFFF32768-49152
r3&C000-&FFFF49152-65535

L'intégralité de cette mémoire vive est adressable directement. A partir du Basic, on utilise les commandes PEEK et POKE pour lire ou modifier le contenu d'une case mémoire.
A l'allumage du CPC, certaines zones de la mémoire sont réservées pour la gestion du système et du Basic. Le CPC utilise également un bloc de 16ko pour gérer l'affichage vidéo. Il s'agit en l'occurence du bloc r3 (&C000-&FFFF). Il est possible de modifier l'adresse d'implantation de la mémoire vidéo grace aux registres &C et &D du contrôleur vidéo. On peut 'augmenter' la taille de la mémoire vidéo à 32ko (pas le sujet de ce texte !).


II Cartographie sommaire de la mémoire vive

Cette liste à la Prévert n'est malheureusement pas complète. Il est apparement difficile de trouver une description exhaustive des fonctions de la zone mémoire &AC00-&BFFF, même dans des bouquins à consonnance religieuse...

&0000-&003FRéservée au système pour les Restart du Z80. On y trouve des instructions permettant de connecter entre autre les ROMS du CPC. Les Restart les plus connus sont RST 0 (en &0000 : init du CPC) et RST &38 (en &0038 ! : adresse de saut du mode IM1 du Z80. Hum, pas le sujet de ce texte non plus !).
&0040-&016FTampon pour la conversion des saisies clavier en BASIC. Les commandes Basic issues du buffer clavier sont codées sous la forme de Token (valeur associée à une commande).
&0170-&A6FF/&ABFFZone de travail du Basic. Contient le programme ainsi que les variables et les caractères redéfinis. Sur un CPC équipé d'un lecteur de disquette, le haut de cette zone est occupé par le DOS (&A700-&ABFF). Il reste donc moins de mémoire disponible pour le Basic. Ceci explique pourquoi quelques vieux jeux Basic très gros ne tournent normalement que sur un CPC sans système disque.

Les petits curieux voudront savoir pourquoi l'on trouve des données à partir de &A67B/&AB7B même si l'on a 'rien fait'. Il s'agit d'une table de caractères, initialisée par défaut (caractères 240 a 255). On peut gagner quelques octets en tapant la commande Basic SYMBOL AFTER 256.

Si vous utilisez des ROM sur votre CPC, ces dernières ont une fâcheuse tendance a se réserver des zones tampon pour pouvoir travailler. Pour connaître la mémoire allouée au Basic, il suffit d'utiliser la commande Basic HIMEM.
&AC00-&B0FF ?Zone de travail du Basic.
&AC8A-&AD89 : tampon saisie clavier (256 octets)
&AE8B-&B08A : pile Basic (512 octets : croissante)
&B100 ?-&B8FFParamètres système (écran, couleurs, touches, gestion des fenêtres, du lecteur de cassettes, etc... ).
&B900-&BDxxVecteurs systèmes : en général, saut sur des routines du Firmware.
464 : &BDCC
664 : &BDBD
6128 : &BDC0
&BDCD-&BDF6Vecteurs d'indirections. On trouve dans cette zone des adresses de saut à quelques routines de la Rom système. Ces adresses sont utilisées par le système lui-même, et permettent de détourner les routines y faisant appel. (ex : le classique &BDEE qui inhibe le reset clavier (CTRL SHIFT ESC) s'il est patché avec la valeur &C9 (commande RETURN en assembleur Z80).
&BDF7-BE3FZone libre.
&BE40-&BE7FZone de travail du système disque
&BE80-&BFFFZone utilisée par la pile du système (décroissante, à partir de &C000-1). Habituellement, la zone &BE80-&BEFC n'est pas écrasée par la pile. Elle est souvent utilisée pour y loger de petites routines ou des loaders de jeux. Caractéristique intéressante, cette zone n'est pas vidée par un reset.
&C000-&FFFFRam video. A noter que sur un écran fixe, les octets des zones suivantes ne sont pas affichés :

&C7D0 - &C7FF &CFD0 - &CFFF
&D7D0 - &D7FF &DFD0 - &DFFF
&E7D0 - &E7FF &EFD0 - &EFFF
&F7D0 - &F7FF &FFD0 - &FFFF

La raison en est simple. Un écran se compose de la manière suivante :
* Une ligne texte se compose de 80 octets
* Un caractère occupe 8 lignes de hauteur
* Le CPC affiche 25 lignes de caractères

A l'aide d'un savant calcul (?), on obtient le résultat suivant : 80x8x25 = 16000.
La taille allouée à la video du CPC est de &4000, soit 16384. Il est donc possible de stocker des petites routines ou des données dans ces zones (attention à ne pas effacer l'écran). Cette particularité a parfois été utilisée par des protections.



III CPC6128 = 128ko !

Pour le CPC6128, on dispose de 128ko de mémoire vive. Pourtant, lorsqu'on met en marche cette machine, on se retrouve seulement avec 42249 octets disponibles pour le Basic. Mais où est donc passé le reste ?
Comme tous les ordinateurs 8bits, le CPC ne peut adresser plus de 64ko. Il n'est donc pas possible d'utiliser telle quelle une éventuelle mémoire supplémentaire. La méthode utilisée pour accéder à cette mémoire est très simple, contrairement à ce que plusieurs ouvrages laissent entendre. La zone mémoire &4000-&7FFF (notre bloc r1 dans le chapitre 1) peut être paginée. Cela signifie qu'à un moment donné, on peut avoir accès au contenu d'un bloc parmi le bloc 1 et les 4 blocs de la mémoire étendue. Ce principe génial (si si !) nous permet de pouvoir utiliser jusqu'a 512ko sur un CPC (voire 1 ou 2mo avec des bidouilles hardwares, dont je ne connais pas le principe).
Concrètement, pour basculer d'une page RAM à une autre, il suffit de faire un OUT &7F00,&Cx où x correspond au bloc mémoire désiré.

OUT &7F00,&C0 : bloc mémoire centrale r1
OUT &7F00,&C4 : bloc mémoire étendue e0
OUT &7F00,&C5 : bloc mémoire étendue e1
OUT &7F00,&C6 : bloc mémoire étendue e2
OUT &7F00,&C7 : bloc mémoire étendue e3

Il est tout à fait possible d'utiliser ces commandes sous Basic, à condition de réserver la zone mémoire, avec la commande MEMORY &3FFF. En pratique, cela peut servir par exemple à stocker des images pour faire des petites animations par recopie en mémoire vidéo.
Il est IMPORTANT de noter que dans tous les cas, le contrôleur vidéo affiche un bloc de mémoire centrale. On ne peut donc pas faire du flipping écran avec de la mémoire étendue.

Petit détail intéressant. Lors d'un reset, le CPC ne réinitialise pas le contenu de la mémoire étendue.


Là où le CPC prouve toute ses ressources, c'est qu'il existe d'autres combinaisons toutes plus intéressantes les unes que les autres.

OUT &7F00,&C1
L'écriture de la ram video se fait dans le bloc mémoire étendue e3 ! Toutes les lectures/écritures entre &C000 et &FFFF se feront dans le bloc étendu e3 et non r3. La ram vidéo centrale est alors inaccessible mais affichée à l'ecran ! Cette bizarrerie a par exemple été utilisée dans le jeu 'Space harrier 2' pour gérer une musique implantée en &C000.

OUT &7F00,&C2
Connexion séquentielle des 4 blocs de mémoire étendue à la place des bank de la mémoire centrale !

zone &0000-&3FFF : bank etendue e0
zone &4000-&7FFF : bank etendue e1
zone &8000-&BFFF : bank etendue e2
zone &C000-&FFFF : bank etendue e3

Pour pouvoir 'basculer' sur la 'nouvelle' RAM, il faut que le code de saut soit présent dans la zone de RAM étendue. Euh, pas clair ? Un exemple : (l'étoile indique où l'on se trouve)

Ram centraleRam étendue e1
* &4000 - DI-
* &4001 - LD BC,&7FC2-
* &4004 - OUT (C),C-
-* &4006 JP coucou

Bon, c'est bien gentil tout ça, mais à quoi cela peut-il servir ? Cette particularité est utilisée par l'interface "The Hacker" avec son mode 'Alternate'. Cela peut également servir a faire du déplombage.

OUT &7F00,&C3
Le bloc mémoire r1 (&4000-&7FFF) est 'échangé' avec le bloc mémoire r3 (&C000-&FFFF). Les lectures/ecritures en &C000-&FFFF se feront dans Le bloc mémoire r1. Cela permet de faire du flipping d'écrans sans avoir à utiliser une routine gérant deux pages écrans à des adresses physiques différentes.


IV Trucs divers

'Nettoyer' un programme Basic


Lorsque l'on saisit un programme Basic, ses lignes contiennent en général des caractères 'blancs'. Avec un gros programme, ces caractères 'parasites' peuvent représenter plusieurs kilo-octets. Il existe un moyen simple pour supprimer ces caractères superflus :

* Sauvegarder le fichier basic en ASCII (commande SAVE"COUCOU",A)
* Faire un POKE &AC00,&FF
* Recharger le fichier précedemment sauvegardé
* Sauvegarder le fichier, c'est fini !

Cette méthode permet par exemple de faire tourner sur CPC6128 des programmes à l'origine faits sur CPC464 et 'trop gros' (ex : 'Le bagne de Népheria'). Problème, certains fichiers sont tellement volumineux qu'on ne peut les charger en mémoire ! Il faut alors faire l'opération précedemment décrite avec un lecteur de K7. Sur un CP6128, il faut au préalable désactiver le système disque. Pour cela, il existe un petit programme paru dans un vieil Amstrad Magazine, "Deconnect".
Pour être exhaustif, il faut signaler l'existence de "Compacta", un programme publié dans un Amstar & CPC. Il permet de supprimer lui aussi les blancs dans un programme Basic, mais sait de plus effacer les lignes contenant des REM (sans modifier les éventuelles adresses de saut à ces lignes, malheureusement.. ), et peut même fusionner des lignes entre elles.

Compacter un programme binaire

Il existe un nombre assez important de compacteurs sur les CPC. Le but est bien évidemment de réduire la taille des programmes, afin de gagner des ko sur nos disquettes. Le compactage est aussi indiqué lorsque l'on veut utiliser des chargeurs Basic pour des jeux commerciaux utilisant 'le bas' de la mémoire du CPC (ex : "Rambo" est implanté en &0040)
Nous allons en faire ici un petit panorama en indiquant les avantages et défauts des programes (le .x indique qu'il existe plusieurs versions du produit) :

  • Zenith 1 et 2 (Esat software)

  • Les deux premiers compacteurs sur CPC ! Il s'agit de programmes commerciaux. Reposant sur la technique de codage des suites d'octets de même valeur, ils ne sont pas très performants. lls ont pourtant été utilisé fort longtemps, aucun autre produit n'existant alors. A réserver aux nostalgiques !

  • Crown cruncher 1.x (Crown of Beng!)

  • Ce compacteur utilise la technique de substitutions de chaines de caractères. Même si le temps de compactage est très long, le résultat est honorable, mais moins bon que Cheese ou CPCT 2.0. Le principal avantage de ce logiciel, c'est qu'il peut compacter de très gros fichiers (zone RAM entre &40 et &AA80 !). De plus, la routine de décompactage n'occupe qu'un espace mémoire restreint (&130) et s'implante systématiquement au dessus de la fin du fichier non compacté. C'est à mon avis le compacteur le mieux adapté pour compresser des jeux...

  • Turbo Imploder 1.1 (Crown of Beng!)

  • Autre logiciel allemand, basé sur le compacteur de Richard Aplin (programmeur de Double dragon qui avait laissé son cruncher sur la version commerciale de ce jeu !), il a des caractéristiques assez originales. Il peut traiter des programmes Basic, il est très rapide au compactage et presque aussi efficace que le Crown cruncher. Mais il présente des défauts :
    - Les fichiers Basic compactés plantent sur CPC plus s'ils sont exécutés directement (m'enfin, ca, ca n'est pas propre à ce programme).

    - Certains gros fichiers ne peuvent être compactés (message Buffer overflow) même si leur taille est largement inférieure aà&A000, limite théorique du programme.

    - Le décompactage est beaucoup plus lent que les autres logiciels. Cela n'a l'air de rien, mais c'est assez oripilant. Un compacteur, à moins de présenter une efficacité monstrueuse, se doit d'avoir une routine de décompression rapide.

    - Pour en finir, il utilise un buffer fixe en &A735, ce qui peut altérer du code dans cette zone.

  • Cheese cruncher 1.x/2.x (Antoine)

  • Le compacteur le plus efficace dans la plupart des cas. Il a quand même quelques défauts : il ne supporte pas les très gros fichiers (taille maximum &9593); les exécutables génerés s'implantent systématiquement en 'haut' de la ram (et plantent le CPC lorsqu'on les chargent avec un Hacker !), ce qui n'est guère pratique en cas de compactages multiples, et enfin, certains émulateurs CPC (CPCEMU) ne le supportent pas.

  • CPCT 1.0/2.0 (Madram)

  • La version 1.0 utilise un système de compactage inédit sur CPC. Interêt de la chose, on peut gagner de la place sur un programme déjà compacté. Le temps de traitement est correct, bien meilleur que le Crown Cruncher. Il peut traiter de gros fichiers (max : &A6BC).
    La version 2.0 apporte une méthode de compactage plus classique, se déclinant en une version simple (1) et étendue (2). Ce logiciel se classe d'emblée parmi les meilleurs en terme de qualité de compression. Mais, cette version en développement est malheureusement outrageusement lente au compactage (mode étendue), et plante parfois.
    On attend donc une version définitive de CPCT 2.0.

  • Turbo Cruncher (Elmsoft)

  • Programme publié dans la revue allemande CPC International. Il a pour principale caractéristique le fait de compacter en faisant du bruit ! Il ne supporte pas les fichiers de plus de &8500 octets (limitation du au fait qu'il est écrit partiellement en Basic). Le taux de compactage est appréciable, meilleur que le Crown Cruncher.

    Grosse limitation, si vous implantez la routine de décompactage dans le fichier généré, le code compacté ne doit pas être chargé en mémoire dans la zone utilisée par le code une fois décompacté. Un exemple :

    Fichier non compacté : départ &1000, longueur &4000, exec &1000
    Fichier compacté : départ &2000, longueur &1200
    Le fichier compacté ne devra pas être logé en mémoire entre &1000 et &4FFF.

    Gros avantage, le fichier compacté est entièrement relogeable. Dans notre exemple, on pourra le stocker en mémoire entre &5000 et &EE80 ! Chose étrange, la routine de décompactage ne tient pas compte de l'éventuelle adresse d'exécution d'un programme.
    Bref, un compacteur intéressant même s'il est un peu plus 'rustique' à utiliser que les autres et doit être réservé à de petits fichiers.
    A noter qu'une nouvelle version de Turbo Cruncher est sortie en 2003 (made in GPA !). Elle est françisée et donne des explications détaillées sur la façon d'utiliser la routine de décompactage.

  • Columbia 1.x (Crtc)

  • Un logiciel anglais, qui tient à la fois du compacteur et de l'archiveur. Avec Columbia, il est possible de traiter des fichiers exécutable, mais aussi n'importe quel fichier. Dans ce dernier cas, le programme se comporte comme un archiveur. Avant de pouvoir utiliser un fichier archive, il faudra au préalable le décompacter avec Columbia. Du côté des performances, cet utilitaire est correct, mais a ses limites. Il nécessite obligatoirement une zone de travail d'environ 13ko, que l'on peut heureusement implanter à peu pres où l'on veut en mémoire, et, plus grave, il est très lent au décompactage (pire que le Turbo Imploder !). Particularité typiquement anglaise, il existe une version cassette de Columbia !

  • Compact (Xavier Brysbaert)

  • Programme paru dans un numero de Amstar & CPC. Il s'agit d'un compacteur utilisant la même technique que Zenith. On ne peut donc pas en attendre des performances éclatantes. Sa seule particularité réside dans le fait que le programme compacté est implanté au même endroit en mémoire que sa source.
    On termine ce panorama avec un petit test grandeur nature sur deux fichiers binaires. Le premier est de taille moyenne, il s'agit du jeu Boulder Dash. Le deuxième est plus gros, sans pour autant atteindre une taille critique pour la majorité des compacteurs, il s'agit du fichier principal de Ghosts'n'goblins.
    Chaque fichier compacte a ensuite été testé. S'il a planté (eh oui, c'est arrivé !), cela est signalé dans le tableau.

    Boulder Dash Taille Ko sur disque Implantation Execution
    Original&702529ko&0200&1F52
    Cheese 2.2&37E615ko&6F1A&6F1A
    Columbia 1.0&3F2B16ko&62C5&A048
    Compact&53F922ko&0200&0200
    CPCT 1.0&533F21ko&2353&75C8
    CPCT 2.0&3AE615ko&3CC0&772C
    Crown cruncher&41F517ko&31B8&7300
    Mega cruncher&53B822ko&0200&0200
    Turbo cruncher&398915kovariablevariable
    Turbo imploder&466A18ko&2CB4&2CB4
    Zenith&53AF22ko&0040&5384
    Zenith 2&514921ko&0140&5236

    G'n'GTailleKo sur disqueImplantationExecution
    Original&8E0036ko&1800&5000
    Cheese 2.2&629025ko&4470&4470
    Columbia 1.0&6D8A28ko&3466&A048 crash !
    Compact&80B333ko&1800&1800
    CPCT 1.0&798B31ko&2D71&2D71
    CPCT 2.0&673B (1)26ko&488B&AF4C
    Crown cruncher&69D227ko&3D5B&A680
    Mega crunchercrash---
    Turbo cruncherTrop gros---
    Turbo imploderBuffer overflow---
    Zenith&806D33ko&0040&0040
    Zenith 2&7EB332ko&0140&7FA0

    Le programme compacté avec le Cheese a un petit bug au niveau de la table des scores.
    A noter que les fichiers compactés par CPCT 2.0 et Crown Cruncher doivent être relogés pour se charger correctement.