Exporter notre jeu TRON pour être utilisé sur CPC ou GX4000Le crossdev c'est sympa et pratique, on a le résultat directement dans l'émulateur mais il y a quelques petites différences avec la création d'un véritable exécutable (et encore plus dans le cas d'une cartouche!!!)
Export aux formats CDT et DSKDans le cas d'un simple exécutable comme c'est le cas pour nous, l'usage du RUN depuis le Basic présente quelques avantages : Les couleurs sont déjà prêtes, l'écran est déjà prêtet est effacé. Comme nous n'utilisons pas les interruptions, on va se 'couper' du système avec les classiques instructions qui ont fait le tour de la rubrique Rubidouille d'Amstrad 100%. di ; couper les interruptions ld hl,#C9FB ; valeur inversée des instructions EI:RET ld (#38),hlIl faut supprimer les lignes faisant référence au SNAPSHOT et les remplacer par BUILDTAPE (pour produire un fichier K7) ainsi qu'un SAVE en fin de source pour le fichier DSK. ; pour rappel, SAVE fichier,debut,taille,DSK,fichierDSK SAVE 'tron.bin',#100,$-#100,DSK,'tron.dsk'Et voici le source complet du TRON BUILDTAPE ORG #100 : RUN #100;====================================== EffaceEcran ;====================================== ld hl,#C000 xor a ; A=0 .loop ld (hl),a ; écrire #00 à l'adresse pointée par HL inc l ; incrémenter seulement L positionne le flag Z une fois revenu à zéro jr nz,.loop ; on boucle donc tant que L est différent de zéro inc h ; même chose pour H, sauf que nous savons ici que L vaut zéro jr nz,.loop ; tant que H ne vaut pas zéro on reboucle ; ici nous avons HL=#0000 nous sommes revenus au début de la mémoire, l'écran est effacer, on s'arrête ; initialiser les coordonnées de notre point ld hl,160 : ld (positionx),hl ld hl,100 : ld (positiony),hl ; position de départ au centre de l'écran ld hl,0 : ld (increment_x),hl ; init! ld hl,-1 : ld (increment_y),hl ; initialiser le premier mouvement vers le haut! ;====================================== AfficherPoint ;====================================== ld bc,(positionx) ld hl,(positiony) call CalculeAdressePixel ld a,(hl) : and c ; on ne conserve que l'éventuel point qu'on veut mettre cp c : jp z,FinDuJeu ; si le point était déjà là, on quitte ld a,(hl) : or c : ld (hl),a ; fusionner le pixel à l'écran call waitVBLstart ; 50Hz call waitVBLstart ; 25Hz call waitVBLstart ; 17Hz allez on speed un peu à 17 images par seconde :) ;====================================== LireLeClavier ;====================================== call lectureMatriceClavier OCTET_CURSEUR_HAUT equ matriceClavier : BIT_CURSEUR_HAUT equ 1 OCTET_CURSEUR_DROITE equ matriceClavier : BIT_CURSEUR_DROITE equ 2 OCTET_CURSEUR_BAS equ matriceClavier : BIT_CURSEUR_BAS equ 4 OCTET_CURSEUR_GAUCHE equ matriceClavier+1 : BIT_CURSEUR_GAUCHE equ 1 OCTET_TOUCHE_ESPACE equ matriceClavier+5 : BIT_TOUCHE_ESPACE equ 128 ; si on appuie sur Espace, on revient à l'effacement de l'écran ld a,(OCTET_TOUCHE_ESPACE) : and BIT_TOUCHE_ESPACE : jp z,EffaceEcran ; ; ; touches du curseur ld a,(OCTET_CURSEUR_HAUT) : and BIT_CURSEUR_HAUT : call z,gererHaut ld a,(OCTET_CURSEUR_BAS) : and BIT_CURSEUR_BAS : call z,gererBas ld a,(OCTET_CURSEUR_DROITE) : and BIT_CURSEUR_DROITE : call z,gererDroite ld a,(OCTET_CURSEUR_GAUCHE) : and BIT_CURSEUR_GAUCHE : call z,gererGauche ; gérer le déplacement du point et le test des bords ld hl,(positionx) : ld de,(increment_x) : add hl,de : ld (positionx),hl ld a,h : cp #FF : jp z,FinDuJeu ; si HL est négatif, alors on quitte xor a : ld de,320 : sbc hl,de : jp z,FinDuJeu ; si HL vaut 320 alors on est sorti de l'écran ld hl,(positiony) : ld de,(increment_y) : add hl,de : ld (positiony),hl ld a,h : cp #FF : jp z,FinDuJeu ; si HL est négatif, alors on quitte ld a,l : cp 200 : jp z,FinDuJeu ; si HL vaut 200, on est sorti de l'écran et on quitte ; jp AfficherPoint ; revenir tout le temps à l'affichage! ;====================================== ; sous-routines de gestion des touches ;====================================== gererHaut ld hl,-1 : ld (increment_y),hl : ld hl,0 : ld (increment_x),hl : ret gererBas ld hl,1 : ld (increment_y),hl : ld hl,0 : ld (increment_x),hl : ret gererGauche ld hl,-1 : ld (increment_x),hl : ld hl,0 : ld (increment_y),hl : ret gererDroite ld hl,1 : ld (increment_x),hl : ld hl,0 : ld (increment_y),hl : ret ;====================================== CalculeAdressePixel ;====================================== ; BC=coordonnée X (0-319) ; HL=coordonnée Y (0-199) ld de,tableau add hl,hl ; adresses 16 bits, il faut indexer de 2 en 2 add hl,de ld a,(hl) : inc hl ld h,(hl) : ld l,a ; HL=adresse de la ligne ld a,c ; on sauvegarde le X avant de diviser par 4 srl bc : srl bc ; diviser le X par 4 pour avoir l'octet en mode 1 add hl,bc ld c,%10000000 ; encre 1 pour le pixel mode 1 le plus à gauche dans l'octet and 3 ; avec le modulo 4 on va savoir quel est le pixel en partant de la gauche jr z,.noShift .Shift srl c dec a jr nz,.Shift .noShift ret ; HL=adresse écran aux coordonnées X/Y données et C est le pixel d'encre 1 ;------------------- adresse_ecran=#C000 largeur_ecran=80 tableau repeat 25 repeat 8 defw adresse_ecran adresse_ecran+=#800 rend adresse_ecran+=largeur_ecran adresse_ecran-=#4000 rend ;============== waitVBLstart ;============== ld b,#F5 .loop in a,(c) : rra : jr c,.loop ; attendre l'absence de VBL ;============== waitVBL ;============== ld b,#F5 .loop in a,(c) : rra : jr nc,.loop ; attendre la VBL ret ;====================================== FinDuJeu ;====================================== ld xl,100 ; 100 VBL = 2 secondes .attente call waitVBLstart : dec xl : jr nz,.attente jp EffaceEcran ; on recommence le jeu! ;====================================== 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 ret matriceClavier defs 10,#FF ;================================================= ; en fin du programme, nos coordonnées sur 16 bits ;================================================= positionx defw 0 positiony defw 0 increment_x defw 0 increment_y defw 0 SAVE 'tron.bin',#100,$-#100,DSK,'tron.dsk'
Export au format CPRL'export au format CPR ne consiste pas qu'à indiquer à l'assembleur d'exporter directement une cartouche. En effet, lorsqu'un Amstrad Plus ou une GX-4000 démarre sur une cartouche, la machinen'est pas initialisée, il faut donc réaliser tout un tas d'opérations préliminaires! Ces opérations se passent exclusivement au début du source, je vous mets directement le source avec les commentaires et un trait de rupture avec le source de base.Chose IMPORTANT à remarquer, le programme commence par s'exécuter DEPUIS la ROM, c'est à dire un espace dans lequel on ne peut pas écrire. Toute écriture surl'adressage de la ROM aura en fait lieu "sous" la ROM, dans la mémoire. Aussi, après nos initialisations, le programme de démarrage va copier le reste de la ROM en mémoire, se lancer et déconnecter la ROM Enfin, léger 'détail' à ne pas oublier pour la GX4000, elle n'a pas de clavier il faut donc changer les contrôles du curseur par le Joystick! BUILDCPR ; indiquer à RASM de produire une cartouche BANK 0 ; ouvrir un espace ROM (16k max) ORG 0 ; l'instruction BANK s'ouvre par défaut sur zéro ; je préfère l'ajouter car on peut se promener d'une ROM à l'autre ; et l'assembleur conserve le pointeur courantdi ; normalement elles sont déjà coupées, mais coupons-les quand même! ; réglages du CRTC pour un écran de type BASIC ld bc,#BC00 : out (c),c : ld bc,#BD00+63 : out (c),c ld bc,#BC01 : out (c),c : ld bc,#BD00+40 : out (c),c ld bc,#BC02 : out (c),c : ld bc,#BD00+46 : out (c),c ld bc,#BC03 : out (c),c : ld bc,#BD00+#8E : out (c),c ld bc,#BC04 : out (c),c : ld bc,#BD00+38 : out (c),c ld bc,#BC05 : out (c),c : ld bc,#BD00+0 : out (c),c ld bc,#BC06 : out (c),c : ld bc,#BD00+25 : out (c),c ld bc,#BC07 : out (c),c : ld bc,#BD00+30 : out (c),c ld bc,#BC08 : out (c),c : ld bc,#BD00+0 : out (c),c ld bc,#BC09 : out (c),c : ld bc,#BD00+7 : out (c),c ld bc,#BC0C : out (c),c : ld bc,#BD00+#30 : out (c),c ld bc,#BC0D : out (c),c : ld bc,#BD00+0 : out (c),c ; initialisation du PPI par défaut ld bc,#F782 : out (c),c ld b,#F4 : out (c),0 : ld b,#F6 : out (c),0 ; initialisation de la mémoire par défaut ld bc,#7FC0 : out (c),c ; configuration type 464, pas de mémoire étendue connectée ; on va se mettre quelques couleurs ld bc,#7F10 : out (c),c : ld a,#55 : out (c),a ; border bleu vif ld bc,#7F00 : out (c),c : ld a,#44 : out (c),a ; fond bleu marine ld bc,#7F01 : out (c),c : ld a,#43 : out (c),a ; crayon jaune clair pastel ; effacer TOUTE la mémoire car comme on l'a vu, elle n'est pas propre au démarrage ld hl,0 : ld a,l InitialiseMemoire ld (hl),a : inc l : jr nz,InitialiseMemoire : inc h : jr nz,InitialiseMemoire ; Installer un retour d'interruption par défaut (même si on ne s'en sert pas dans ce programme...) ld hl,#C9FB ; ld (#38),hl ; copier le programme de la ROM à la RAM ld hl,#100 : ld de,#100 ; au même endroit! ld bc,fin_du_source-#100 ldir ; COPIER! ; Installer un pointeur de pile juste avant le programme en #100 ld sp,#100 ld bc,#7F80+%1101 : out (c),c ; déconnecter toutes les ROM et MODE 1!!! ; le programme va continuer d'ici à #100 dans les zéros de la mémoire ; qu'on vient juste d'initialiser, ça tombe bien ; nop, nop, nop ;=========== source de BASE =========================== ORG #100 ; le RUN devient obsolète, une cartouche démarre TOUJOURS en 0 EffaceEcran ld hl,#C000 xor a ; A=0 .loop ld (hl),a ; écrire #00 à l'adresse pointée par HL inc l ; incrémenter seulement L positionne le flag Z une fois revenu à zéro jr nz,.loop ; on boucle donc tant que L est différent de zéro inc h ; même chose pour H, sauf que nous savons ici que L vaut zéro jr nz,.loop ; tant que H ne vaut pas zéro on reboucle ; ici nous avons HL=#0000 nous sommes revenus au début de la mémoire, l'écran est effacer, on s'arrête ; initialiser les coordonnées de notre point ld hl,160 : ld (positionx),hl ld hl,100 : ld (positiony),hl ; position de départ au centre de l'écran ld hl,0 : ld (increment_x),hl ; init! ld hl,-1 : ld (increment_y),hl ; initialiser le premier mouvement vers le haut! ;====================================== AfficherPoint ;====================================== ld bc,(positionx) ld hl,(positiony) call CalculeAdressePixel ld a,(hl) : and c ; on ne conserve que l'éventuel point qu'on veut mettre cp c : jp z,FinDuJeu ; si le point était déjà là, on quitte ld a,(hl) : or c : ld (hl),a ; fusionner le pixel à l'écran call waitVBLstart ; 50Hz call waitVBLstart ; 25Hz call waitVBLstart ; 17Hz allez on speed un peu à 17 images par seconde :) ;====================================== LireLeClavier ;====================================== call lectureMatriceClavier OCTET_JOYSTIK_HAUT equ matriceClavier+9 : BIT_JOYSTIK_HAUT equ 1 OCTET_JOYSTIK_BAS equ matriceClavier+9 : BIT_JOYSTIK_BAS equ 2 OCTET_JOYSTIK_GAUCHE equ matriceClavier+9 : BIT_JOYSTIK_GAUCHE equ 4 OCTET_JOYSTIK_DROITE equ matriceClavier+9 : BIT_JOYSTIK_DROITE equ 8 OCTET_TOUCHE_ESPACE equ matriceClavier+9 : BIT_TOUCHE_ESPACE equ 16 ; si on appuie sur Espace, on revient à l'effacement de l'écran ld a,(OCTET_TOUCHE_ESPACE) : and BIT_TOUCHE_ESPACE : jp z,EffaceEcran ; ; ; touches du curseur ld a,(OCTET_JOYSTIK_HAUT) : and BIT_JOYSTIK_HAUT : call z,gererHaut ld a,(OCTET_JOYSTIK_BAS) : and BIT_JOYSTIK_BAS : call z,gererBas ld a,(OCTET_JOYSTIK_DROITE) : and BIT_JOYSTIK_DROITE : call z,gererDroite ld a,(OCTET_JOYSTIK_GAUCHE) : and BIT_JOYSTIK_GAUCHE : call z,gererGauche ; gérer le déplacement du point et le test des bords ld hl,(positionx) : ld de,(increment_x) : add hl,de : ld (positionx),hl ld a,h : cp #FF : jp z,FinDuJeu ; si HL est négatif, alors on quitte xor a : ld de,320 : sbc hl,de : jp z,FinDuJeu ; si HL vaut 320 alors on est sorti de l'écran ld hl,(positiony) : ld de,(increment_y) : add hl,de : ld (positiony),hl ld a,h : cp #FF : jp z,FinDuJeu ; si HL est négatif, alors on quitte ld a,l : cp 200 : jp z,FinDuJeu ; si HL vaut 200, on est sorti de l'écran et on quitte ; jp AfficherPoint ; revenir tout le temps à l'affichage! ;====================================== ; sous-routines de gestion des touches ;====================================== gererHaut ld hl,-1 : ld (increment_y),hl : ld hl,0 : ld (increment_x),hl : ret gererBas ld hl,1 : ld (increment_y),hl : ld hl,0 : ld (increment_x),hl : ret gererGauche ld hl,-1 : ld (increment_x),hl : ld hl,0 : ld (increment_y),hl : ret gererDroite ld hl,1 : ld (increment_x),hl : ld hl,0 : ld (increment_y),hl : ret ;====================================== CalculeAdressePixel ;====================================== ; BC=coordonnée X (0-319) ; HL=coordonnée Y (0-199) ld de,tableau add hl,hl ; adresses 16 bits, il faut indexer de 2 en 2 add hl,de ld a,(hl) : inc hl ld h,(hl) : ld l,a ; HL=adresse de la ligne ld a,c ; on sauvegarde le X avant de diviser par 4 srl bc : srl bc ; diviser le X par 4 pour avoir l'octet en mode 1 add hl,bc ld c,%10000000 ; encre 1 pour le pixel mode 1 le plus à gauche dans l'octet and 3 ; avec le modulo 4 on va savoir quel est le pixel en partant de la gauche jr z,.noShift .Shift srl c dec a jr nz,.Shift .noShift ret ; HL=adresse écran aux coordonnées X/Y données et C est le pixel d'encre 1 ;------------------- adresse_ecran=#C000 largeur_ecran=80 tableau repeat 25 repeat 8 defw adresse_ecran adresse_ecran+=#800 rend adresse_ecran+=largeur_ecran adresse_ecran-=#4000 rend ;============== waitVBLstart ;============== ld b,#F5 .loop in a,(c) : rra : jr c,.loop ; attendre l'absence de VBL ;============== waitVBL ;============== ld b,#F5 .loop in a,(c) : rra : jr nc,.loop ; attendre la VBL ret ;====================================== FinDuJeu ;====================================== ld xl,100 ; 100 VBL = 2 secondes .attente call waitVBLstart : dec xl : jr nz,.attente jp EffaceEcran ; on recommence le jeu! ;====================================== 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 ret matriceClavier defs 10,#FF ;================================================= ; en fin du programme, nos coordonnées sur 16 bits ;================================================= positionx defw 0 positiony defw 0 increment_x defw 0 increment_y defw 0 fin_du_sourceEt voilà, nous avons notre TRON autonome avec un border différend du fond! 
Roudoudou CPCrulez[Content Management System] v8.732-desktop Page créée en 044 millisecondes et consultée 21 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. |
|