Avant d'attaquer la lecture de cet article, assurez-vous d'avoir téléchargé la dernière version de [ RASM ], à minima une 2.3.1 !Les structures, c'est pratique! Je pensais vous faire un petit exemple pour vous montrer comment réaliser un menu flexible (au hasard pour un de vos futurs programmes!). Pour notre menu, nous aurons des libellés à placer à l'écran, un texte à afficher et on va relier notre entrées du menu avec des champs précédent/suivants faisant le lien entre les structures, ainsi,nul besoin de savoir combien de structures nous avons à gérer, on saute d'une à l'autre ce qui va nous aider aussi pour la gestion du curseur. Enfin, on associera une action (l'adresse d'une routine) à notre entrée de menu, si l'utilisateur valide l'entrée, alors on saute à la routine "action". struct entite_menu adresse_ecran defw libelle defs 20 suivant defw precedent defw action defw actif defb endstructOn va s'installer 3 entrées de menu qui vont appeler des routines qui changent les couleurs de l'écran. On rempli nos structures lors de la déclaration : - premier paramètre, le type de structure (entite_menu) - deuxième paramètre, le nom de l'instance de la-dite structure (entree1, entree2, ...) - troisième paramètre, le nombre de structures, nous on va les déclarer une par une mais on peut faire des tableaux - les autres paramètres correspondent chacun aux champs de la structure, on peut s'arrêter avant le dernier, ça complète alors par défaut struct entite_menu entree1,1,#C000+80*0,'Jaune sur Bleu\xFF',entree2,entree3,JauneBleu,33 ; activer la première struct entite_menu entree2,1,#C000+80*2,'Blanc sur Rouge\xFF',entree3,entree1,BlancRouge struct entite_menu entree3,1,#C000+80*4,'Noir sur Gris\xFF',entree1,entree2,NoirGrisIl va nous falloir une routine qui initialise toutes les entrées. L'indexation des champs va se faire facilement avec l'usage des registres d'index IX ou IY. AfficheEntrees ld iy,entree1 .boucle ld hl,(iy+entite_menu.adresse_ecran) : ld (position_char),hl ld a,(iy+entite_menu.actif) : call affiche_caractere ld de,iy : ld hl,entite_menu.libelle : add hl,de : call affiche_chaine ld a,(iy+entite_menu.actif) : call affiche_caractere ld de,(iy+entite_menu.suivant) : ld iy,de ld hl,entree1 : or a : sbc hl,de ; test rebouclage jr nz,.boucle retJ'ai bouclé jusqu'à revenir à la première entrée, ça permet de modifier la liste et ne pas se soucier du nombre d'entrées. On pouvait aussi parcourir linéairementnotre tableau et sauter de structure en structure. Il va nous falloir aussi 3 routines pour changer les couleurs (voir 4 pour factoriser un peu le code) JauneBleu ld hl,#444A : jr setColor BlancRouge ld hl,#4B4C : jr setColor NoirGris ld hl,#5440 setColor ld bc,#7F10 : out (c),c : out (c),h : out (c),0 : out (c),h : ld c,1 : out (c),c : out (c),l : retPour la gestion, 3 touches, haut/bas pour naviguer, espace pour valider. L'entrée active devra être d'une autre couleur. gestionMenu call JauneBleu ; couleurs par défaut call AfficheEntrees ; init de l'affichage .laBoucle call lectureMatriceClavier ld a,(OCTET_CURSEUR_HAUT) : and BIT_CURSEUR_HAUT : jr z,.versLeHaut ld a,(OCTET_CURSEUR_BAS) : and BIT_CURSEUR_BAS : jr z,.versLeBas ld a,(OCTET_ESPACE) : and BIT_ESPACE : jr z,.action jr .laBoucle.action ld hl,laBoucle : push hl ; l'action reviendra ici ld hl,(iy+entite_menu.action) : jp (hl) ; exécuter l'action .versLeHaut ld de,(iy+entite_menu.precedent) : ld iy,de : jr .laBoucle .versLeBas ld de,(iy+entite_menu.suivant) : ld iy,de : jr .laBoucle J'ai gardé le source de l'article précédent, on laisse tout en ROM, le menu, la fonte, les routines! On ajoute le tableau des touches en mémoire vive, il faut bien pouvoir écrire dedans :) Vous aurez besoin du [ binaire de la fonte ] pour assembler ce source struct entite_menu adresse_ecran defw libelle defs 20 suivant defw precedent defw action defw actif defb endstruct OCTET_CURSEUR_HAUT equ matriceClavier+0 : BIT_CURSEUR_HAUT equ 1 OCTET_CURSEUR_DROITE equ matriceClavier+0 : BIT_CURSEUR_DROITE equ 2 OCTET_CURSEUR_BAS equ matriceClavier+0 : BIT_CURSEUR_BAS equ 4 OCTET_CURSEUR_GAUCHE equ matriceClavier+1 : BIT_CURSEUR_GAUCHE equ 1 OCTET_ESPACE equ matriceClavier+5 : BIT_ESPACE equ 128 MODE_0 equ 0 : MODE_1 equ 1 : MODE_2 equ 2 : MODE_3 equ 3 : CLEAR_INT equ %10000 ROM_OFF equ %1100 : ROM_BOTH equ 0 : ROM_UP equ %100 : ROM_LOW equ %1000 : INTRESET equ %10000 macro RMR tags : ld a,{tags}+%10000000 : ld b,#7F : out (c),a : mendBUILDSNA : BANKSET 0 ORG #100 : RUN #100 : LD SP,#100 RMR ROM_UP | MODE_1 ; activer la ROM haute + Mode 1 ld bc,#DF00+{bank}affiche_caractere : out (c),c ; sélectionner la ROM qui contient la routine, la fonte, le message jp gestionMenu position_char defw #C000 ; besoin d'avoir cette VARIABLE en mémoire vive pour la modifier entree_active defw entree1 ; entree par défaut matriceClavier defs 10,#FF charset ' ABCDEFGHIJKLMNOPQRSTUVWXYZ!()*+,-./0123456789:;<=>?@_abcdefghijklmnopqrstuvwxyz#',0 struct entite_menu entree1,1,#C000+80*0,'Jaune sur Bleu\xFF',entree2,entree3,JauneBleu,33 struct entite_menu entree2,1,#C000+80*2,'Blanc sur Rouge\xFF',entree3,entree1,BlancRouge struct entite_menu entree3,1,#C000+80*4,'Noir sur Gris\xFF',entree1,entree2,NoirGris charset ROMBANK 15 ; peu importe le numéro! org #C000 ; par contre une ROM haute commence TOUJOURS en #C000! affiche_chaine ld a,(hl) : inc hl ; récupérer la valeur dans le tableau et incrémenter le pointeur cp #FF : ret z ; terminateur? push hl : call affiche_caractere : pop hl ; on a besoin de conserver notre pointeur HL jr affiche_chaine
affiche_caractere ; nos caractères font 48 octets add a : ld h,0 : ld l,a : add hl,hl : add hl,hl : add hl,hl ; x 16 ld bc,hl : add hl,hl : add hl,bc ; x 48 ld bc,fonte : add hl,bc ; HL=adresse des données du caractère dans le tableau fonte ld de,(position_char) ; on récupère la position du curseur ld xl,16 ; nombre de lignes ld bc,#10FF ; le LDI décrémente BC donc on charge C au maximum pour que B puisse servir de compteur affiche_ligne_caractere push de : ldi 3 : pop de ld a,d : add 8 : ld d,a : and #38 : jr nz,.noOVF ld a,80 : add e : ld e,a : ld a,#C0 : adc d : ld d,a : res 3,d .noOVF djnz affiche_ligne_caractere ; avancer le curseur ld hl,(position_char) : inc hl : inc hl : inc hl : ld (position_char),hl ret lectureMatriceClavier ld hl,matriceClavier ld bc,#f782 out (c),c ld bc,#f40e ld e,b out (c),c ld bc,#f6c0 ld d,b out (c),c out (c),0 ld bc,#f792 out (c),c ld a,#40 ld c,d .loop ld b,d out (c),a ; sélectionner la ligne ld b,e ini ; lire et stocker dans notre tableau inc a inc c jr nz,.loop ld bc,#f782 out (c),c ret afficheEntrees push iy : ld iy,entree1 .boucle ld hl,(iy+entite_menu.adresse_ecran) : ld (position_char),hl ld a,(iy+entite_menu.actif) : call affiche_caractere ld de,iy : ld hl,entite_menu.libelle : add hl,de : call affiche_chaine ld a,(iy+entite_menu.actif) : call affiche_caractere ld de,(iy+entite_menu.suivant) : ld iy,de ld hl,entree1 : or a : sbc hl,de ; test rebouclage jr nz,.boucle pop iy : ret gestionMenu call JauneBleu ; couleurs par défaut ld iy,entree1 .laBoucle call afficheEntrees ; init de l'affichage call lectureMatriceClavier ld a,(OCTET_CURSEUR_HAUT) : and BIT_CURSEUR_HAUT : jr z,.versLeHaut ld a,(OCTET_CURSEUR_BAS) : and BIT_CURSEUR_BAS : jr z,.versLeBas ld a,(OCTET_ESPACE) : and BIT_ESPACE : jr z,.action jr .laBoucle .action ld hl,.laBoucle : push hl ; l'action reviendra ici ld hl,(iy+entite_menu.action) : jp (hl) ; exécuter l'action .versLeHaut ld (iy+entite_menu.actif),0 ld de,(iy+entite_menu.precedent) : ld iy,de : ld (iy+entite_menu.actif),33 : jr .laBoucle .versLeBas ld (iy+entite_menu.actif),0 ld de,(iy+entite_menu.suivant) : ld iy,de : ld (iy+entite_menu.actif),33 : jr .laBoucle JauneBleu ld hl,#444A : jr setColor BlancRouge ld hl,#4B4C : jr setColor NoirGris ld hl,#5440 setColor ld bc,#7F10 : out (c),c : out (c),h : out (c),0 : out (c),h : ld c,1 : out (c),c : out (c),l : ret fonte incbin 'simpleFonte.bin' ; définir le charset pour les messages 
Bon, c'est minimaliste. Déjà, je m'aperçois que la fonte est bien décalée vers le haut pour les minuscules et puis surtout le curseur va beaucoup trop vite. Pour le curseur, on peut se faire une fonction qui attend qu'on appuie sur aucune touche avant de continuer ClavierDisponible call lectureMatriceClavier ld hl,matriceClavier : ld b,10 .boucle ld a,(hl) : cpl : or a : jr nz,ClavierDisponible : djnz .boucle retEt on insère l'appel dans la gestion haut/bas ld de,(iy+entite_menu.precedent) : ld iy,de : ld (iy+entite_menu.actif),33 : call ClavierDisponible : jr .laBoucle [ ... ] ld de,(iy+entite_menu.suivant) : ld iy,de : ld (iy+entite_menu.actif),33 : call ClavierDisponible : jr .laBouclePour nos glitchs de fonte, il faudrait reprendre le fichier PNG que j'ai un peu trop fait à l'arrache (vous savez faire?) Roudoudou CPCrulez[Content Management System] v8.732-desktop Page créée en 013 millisecondes et consultée 14 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. |
|