Description du format d'une ROM, pour qu'elle soit reconnue est installée automatiquement au démarrage du BASICDescription: Les ROMs (upper ROM) sont situées en mémoire de &C000 a &FFFF. Pour sélectionner et activer une ROM particulière, reportez-vous aux articles sur le GATE ARRAY ici et sur l'activation des ROMS ici Pour être reconnue par le CPC, Le premier octet de la ROM doit être &01. Ceci indique au BASIC que cette ROM contient un programme qui sera exécuté en tâche de fond (Background), contrairement à la ROM BASIC qui contient la valeur &80 pour indiquer qu'il s'agit de la tâche princiaple (FOREGROUND) Des informations complémentaires, mais non indispensables sont les 3 octets suivants. Ils correspondent au numéro de version de la ROM. Exemple pour la version 1.23 il faudra mettre les octets &01 &02 &03. Toutes ces informations peuvent être visualisées à l'aide par exemple de la ROM Maxam 1.5, grâce à la commande ùHELP. Les 2 octets suivants doivent donner l'adresse de la table des commandes externes définies par la ROM. Ensuite se trouve la table des adresses à exécuter, correspondant à la table décrite précédemment. Ces 2 informations ont le même format que celui utilisé par le CALL &BCD1, à savoir: La table est composée d'entrées dont les noms sont des chaînes de caractères dont la fin est déterminée lorsque la valeur d'un caractère est supérieure à &7F Un Octet &00 est placé à la fin de la table. Exemple, pour une ROM avec 3 commandes externes: org &c000 ; DEFB &01 ; bg ROM ; DEFB &07,&04,&01 ; Version 7.41 ; DEFW RSX_TABLE ; Adresses des noms des Commandes externes .JUMP_TABLE JP INIT_ROM ; Adresse d'execution lors du demarrage JP COMMANDE1 JP COMMANDE2 JP COMMANDE3 .RSX_TABLE ; TEXT "INITIALISE MA RO","M"+&80 ; TEXT "COMMANDE","1"+&80 ; TEXT "COMMANDE","2"+&80 ; TEXT "COMMANDE","3"+&80 ; DEFB 0 ; FINOn remarquera en particulier qu'il y a en réalité 4 commandes déclarées: "COMMANDE1","COMMANDE2","COMMANDE3" et "INITIALISE MA ROM". La première commandes déclarée (dans notre exemple "INITIALISE MA ROM") va être automatiquement appelée par le BASIC lors du démarrage et sera donc la commande d'initialisation de la ROM. Il est recommandé d'utiliser pour cette commande externe un nom de commande qui ne pourra pas être utilisé en BASIC, comme c'est le cas ici à cause des espaces. Ceci évidemment dans le but d'éviter d'appeler plusieurs fois la commande d'initialisation.Comme vous l'avez compris, après avoir automatiquement installé vos commandes externes, le BASIC va exécuter la première commande décrite par la ROM à savoir ici: "INITIALISE MA ROM". Pour être installée correctement par le CPC, Cette première commande externe doit répondre à certaines obligations. En entrée, HL contient l'adresse jusqu'à laquelle la mémoire est libre. Si la seule autre ROM utilisée est AMSDOS, alors HL vaudra &A700, car AMSDOS et le BASIC utilisent la zone mémoire de &A700 a &BFFF. En sortie, HL contient l'adresse jusqu'à laquelle la mémoire est libre. Cette valeur tient désormais compte de la mémoire nécessitée par la ROM. Par exemple si la ROM requiert 9 octets en RAM pour stocker des informations, il faudra retourner dans HL sa valeur en entrée moins 9. Les autres registres (sauf AF) ne doivent pas être affectés. De plus si l'initialisation s'est bien passée alors il faut positionner le Carry à 1. Dans le cas contraire (pas assez de mémoire par exemple) alors mettre le carry à 0. En retour, le BASIC va tenir compte de cette nouvelle valeur pour la prochaine ROM à installer (sachant que le BASIC cherche d'abord à installer la ROM 7, puis 6, etc, jusqu'à 0). Bien sur, plus la ROM nécessite de RAM pour être utilisée, plus la valeur Max de HIMEM en BASIC va diminuer. Exemple complet : ; Cette ROM definit les commandes: ; ùAZERTY qui change le mapping des touches en RAM pour simuler un clavier azerty ; ùQWERTY qui change le mapping des touches en RAM pour simuler un clavier qwerty ; ùABOUT qui affiche un message. org &c000 ; DEFB &01 ; bg ROM ; DEFB &01,&00,&00 ; Version 1.00 ; DEFW RSX_TABLE ; Adresses des noms des Commandes externes JP INIT_AZERTY ; Adresse d'execution lors du demarrage JP AZERTY jp QWERTY jp ABOUT .rsx_table ; text "INIT CLAVIE","R"+&80 ; text "AZERT","Y"+&80 ; text "QWERT","Y"+&80 ; text "ABOU","T"+&80 ; defb 0 ; FIN .init_AZERTY push hl PUSH DE call AZERTY pop DE pop hl ret .AZERTY ld hl,TABLE_AZERTY call COPIE_TABLE ret .QWERTY ld hl,TABLE_QWERTY .COPIE_TABLE ld BC,CHAR_TABLE_LEN ld DE,CHAR_TABLE ldir ret .ABOUT ld hl,ABOUT_TEXT1 .textout ld a,(hl) call &BB5A inc hl or a jr nz,textout ret .ABOUT_TEXT1 text "Transcription des touches pour clavier AZERTY",10,13 text "Par Masterglob, 2004",10,13,0 .TABLE_AZERTY db &F0 ,&F3 ,&F1 ,&89 ,&86 ,&83 ,&8B ,&8A ,&F2 ,&E0 ,&87 ,&88 ,&85 ,&81 ,&82 ,&80 db &2A ,&5B ,&0D ,&24 ,&84 ,&FF ,&32 ,&FF ,&3D ,&29 ,&A0 ,&70 ,&7C ,&2C ,&21 ,&3A db &40 ,&5E ,&6F ,&69 ,&6C ,&6B ,&6D ,&3B ,&5F ,&60 ,&75 ,&79 ,&68 ,&6A ,&6E ,&20 db &2D ,&28 ,&72 ,&74 ,&67 ,&66 ,&62 ,&76 ,&27 ,&22 ,&65 ,&77 ,&73 ,&64 ,&63 ,&78 db &26 ,&23 ,&FC ,&71 ,&09 ,&61 ,&FD ,&7A ,&10 ,&2A ,&2F ,&2D ,&2B ,&3C ,&FF ,&7F db &F4 ,&F7 ,&F5 ,&89 ,&86 ,&83 ,&8B ,&8A ,&F6 ,&E0 ,&87 ,&88 ,&85 ,&81 ,&82 ,&80 db &75 ,&7B ,&0D ,&A3 ,&84 ,&FF ,&6E ,&FF ,&2B ,&30 ,&A2 ,&50 ,&25 ,&3F ,&A6 ,&2F db &30 ,&39 ,&4F ,&49 ,&4C ,&4B ,&4D ,&2E ,&38 ,&37 ,&55 ,&59 ,&48 ,&4A ,&4E ,&20 db &36 ,&35 ,&52 ,&54 ,&47 ,&46 ,&42 ,&56 ,&34 ,&33 ,&45 ,&57 ,&53 ,&44 ,&43 ,&58 db &31 ,&32 ,&FC ,&51 ,&09 ,&41 ,&FD ,&5A ,&10 ,&2A ,&2F ,&2D ,&2B ,&3E ,&FF ,&7F db &F8 ,&FB ,&F9 ,&89 ,&86 ,&83 ,&8C ,&8A ,&FA ,&E0 ,&87 ,&88 ,&85 ,&81 ,&82 ,&80 db &00 ,&1B ,&0D ,&A4 ,&84 ,&FF ,&00 ,&FF ,&7D ,&5D ,&00 ,&10 ,&00 ,&00 ,&00 ,&00 db &40 ,&5E ,&0F ,&09 ,&0C ,&0B ,&0D ,&00 ,&5C ,&60 ,&15 ,&19 ,&08 ,&0A ,&0E ,&FF db &7C ,&5B ,&12 ,&14 ,&07 ,&06 ,&02 ,&16 ,&7B ,&23 ,&05 ,&17 ,&13 ,&04 ,&03 ,&18 db &FF ,&7E ,&FC ,&11 ,&E1 ,&01 ,&FE ,&1A ,&10 ,&2A ,&2F ,&2D ,&2B ,&00 ,&FF ,&7F db &07 ,&03 ,&4B ,&FF ,&FF ,&FF ,&FF ,&FF ,&AB ,&BF ,&01 ,&30 ,&01 ,&31 ,&01 ,&32 db &01 ,&33 ,&01 ,&34 ,&01 ,&35 ,&01 ,&36 ,&01 ,&37 ,&01 ,&38 ,&01 ,&39 ,&01 ,&2E db &01 ,&0D ,&05 ,&52 ,&55 ,&4E ,&22 ,&0DVous allez demander: "Comment peut-on récupérer l'adresse de la zone mémoire que le système nous a attribué?"S'il s'agit de la fonction d'initialisation, nous connaissons déjà la réponse puisque c'est grâce au registre HL que nous pouvons choisir son emplacement. Lorsque une commandes externe ùCOMMANDE1 est appelée depuis le BASIC, les conditions d'entrée dans la routine sont les suivantes: 1. IX Contient la liste des paramètres (IX+&00),(IX+&01) contient l'adresse ou la valeur du dernier paramètre, (IX+&02),(IX+&03) l'adresse de l'avant dernier etc... 2. A contient le nombre de paramètres 3. IY contient l'adresse mémoire du début de la zone réservée à la ROM en RAM. 4. C contient le numéro de la ROM (0..7) Autre exemple: org &c000 ; DEFB &01 ; bg ROM ; DEFB &07,&04,&01 ; Version 7.41 ; DEFW RSX_TABLE ; Adresses des noms des Commandes externes .JUMP_TABLE JP INIT_ROM ; Adresse d'execution lors du demarrage JP ECRIT JP LIT .RSX_TABLE TEXT "INITIALISE MA RO","M"+&80 ; TEXT "ECRI","T"+&80 ; TEXT "LI","T"+&80 ; DEFB 0 ; FIN .INIT_ROM ; DEC HL ; DEC HL RET .LIT OR A RET Z ;On ne fait rien si il n'y a pas de parametres LD H,(IX+1) ; Lecture du parametre LD L,(IX+0) LD (IY+1),H ; Ecriture du parametre en memoire LD (IY+0),L RET .ECRIT LD A,1 CALL &BB5A LD A,(IY+1) ; Lecture du parametre CALL &BB5A LD A,1 CALL &BB5A LD A,(IY+0) ; Lecture du parametre CALL &BB5A RETPlus compliqué: Imaginons maintenant que le but de la ROM soit de surcharger des routines systèmes, via les vecteurs d'interruption. Par exemple, vous voulez écrire un programme qui utilise une autre ressource que la cassette ou AMSDOS pour lire/écrire dans des fichiers (RAM DISC par exemple). Nous allons traiter un exemple simple ou la ROM va surcharger les routines basic de gestion des fichiers (&BC77 à &BC9B) et afficher "Aujourd'hui j'ai pas envie de travailler" au lieu de faire ce qu'on lui demande: org &c000 ; defb &01 ; bg ROM ; defb &01,&00,&00 ; Version 1.0 ; defw rsx_table ; Adresses des Commandes externes JP INIT_ROM ; Adresse d'execution lors du demarrage JP FATIGUE ; .rsx_table text "INIT MA RO","M"+&80 ; text "FATIGU","E"+&80 defb 0 ; FIN ; INIT_ROM reserve 3 octets en RA et y inscrit ; l'adresse de p_func_sel et le numéro de la ROM courante .INIT_ROM push bc push DE ld de,-3 ; Place reservee en RAM add hl,de push hl ld de,p_func_sel ; Adresse de la routine de selection de fonction inc hl ld (hl),e inc hl ld (hl),d inc hl call &b912 ;Get ROM number into A register ld (hl),a pop hl POP DE pop bc ; scf ret ;FATIGUE change les vecteurs d'interruption de gestion des fichiers .fatigue ld hl,coucou_t call textout ; Affiche un texte push IY ; Sauve l'adresse des donnees en RAM pop de ; et recuperation dans DE ; En ecrivant &DF puis la valeur de IY qui contient ; maintenant l'adresse de p_func_sel on va demander ; au systeme d'executer le code en p_func_sel ; Nota; toutes ces fonction peuvent etre reactivees correctement ; avec ùDISC ou ùTAPE qui fait le meme genre ; de traitement ld hl,&BC77 ; override BASIC function ld b,13 ; 13 functions .fatigue1 ld (hl),&DF inc hl ld (hl),e inc hl ld (hl),d inc hl djnz fatigue1 ret ; Cette fonction recupere l'argument dans ; la pile correspondant à l'adresse d'execution ; de la fonction demandee et l'execute ; Le principe est de determiner l'adresse ; du call qui a ete effectue (exemple CAT => call &BC9B) ; et d'en deduire quelle fonction appeller. ; COmme la table des appels ci-dessous est dans le ; meme ordre que celle de &BC77 a &BC9B, ; on a simplement une translation à faire sur l'adresse demandee. .p_func_sel di ex af,af' exx ld a,c pop de pop bc pop hl ex (sp),hl push bc push de ld c,a ld b,&7F ; pour HL=&bc9e (fonction Cat ) il faut avoir jp_cat ld de,jp_cat-&bc9e add hl,de push HL ;adresse to jump exx ex af,af' ei jp #BE7F ; execution... ; Overriding BASIC functions .jp_1rst_block_read jp greve ;&bc77 .jp_close_file jp greve ;&bc7a .jp_cancel_i_file jp greve ;&bc7d .jp_read_char jp greve ;&bc80 .jp_read_file jp greve ;&bc83 .jp_unread_char jp greve ;&bc86 .jp_test_EOF jp greve ;&BC89 .jp_openout ;jp greve ;&BC8C .jp_closeout jp greve ;&BC8F .jp_cancel_o_file jp greve ;&bC92 .jp_write_char jp greve ;&BC95 .jp_write_file jp greve ;&BC98 .jp_cat ;jp greve ;&BC9B .greve ld hl,texte2 call textout ; Pour signaler au systeme que la commande a echoue ( a cause de la greve) ; on positionne C a 0 xor a ret .textout ld a,(hl) inc hl or a ret z push af and &7f call &bb5a pop af and &80 jr z,textout ret .coucou_t text "C'est la greve",10,13,#80 .texte2 text "Non on ne veut pas travailler!",10,13,#80Sur cet exemple, on s'est amusé à faire un traitement compliqué alors que finalement, tous les vecteurs surchargés appellent la même procédure (greve). Le but était de montrer comment pouvoir distinguer simplement quel vecteur est utilisé.A noter que la routine p_func_sel n'est pas de moi, elle est intégralement recopiée d'une ROM surchargeant ces vecteurs pour l'émulateur (ROM CPCDOS). Donc ne m'en voulez pas si elle parait un peu compliquée... Elle est cependant nécessaire pour appeler une routine qui se trouve dans une ROM. Si le programme avait été recopié en RAM par exemple, on aurait pu se contenter d'écrire JP MA_ROUTINE_CAT en &BC9B,etc ... L'intérêt de ce genre de manipulation est qu'un ùDISC, ùTAPE (ou ùDOS sous émulateur, ou ùPCDISC pour les connaisseurs) réinitialise la table des vecteurs, étant donné que les autres ROMs procèdent de la même façon. N'hésitez pas à faire vos suggestion à Masterglob http://site.voila.fr/masterglob/CPC ( Attention le site est HS pour le moment) ★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser... |
CPCrulez[Content Management System] v8.73-desktop/c Page créée en 302 millisecondes et consultée 3518 foisL'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko. |
|
|