MSX Village forum

La Place des Développeurs UFO de 10 lignes basic à l'ASM Programmation d'UFO en ASM par un nul

MSXosaure Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 03/10/2009 à 00h09

Messages: 774

Le 17/08/2010 à 11h29
Voilà mes début en ASM et pour ainsi dire mon premier jeu en assembleur.
J'ai mis pas mal de commentaire par endroit, je pense que le découpage du programme n'est pas idéal, ça date de juin je n'y est pas retouché depuis.

C'est plus fluide que l'original en basic et j'ai pu y ajouté une petite musique.

ufo.zip


Le MSXien le plus à l'ouest :fou ... ou presque :D
osaurer
   
Visiteur

Vagabond

Rang

Avatar

Message : 0

Le 17/08/2010 à 12h02
Pas mal ton programme! Et c'est sympa d'avoir fourni la rom :)
Je vais me servir du source pour mes tests sur cross-compilateurs.
Tu as compilé avec quoi au fait ?

Je connais très mal l'assembleur z80, mais j'ai quand même jeté un coup d'oeil par curiosité :)

J'ai l'impression que tu utilises les routines du bios pour l'affichage, n'est-ce pas ?

A quoi fait référence "LDIRVM" ?
Ah j'ai trouvé, c'est un alias pour 0x5C, donc un point d'entrée du bios.

J'ai jeté un coup d'oeil à ton timing, mais je n'ai pas compris comment tu faisais, ça me parait assez compliqué.

Le but est-il de faire une boucle vide, et de rester dans la boucle un certain laps de temps ?
Ne serait-il pas mieux d'intégrer ton code dans la boucle, et de faire les traitements uniquement sur un modulo de l'horloge. Ainsi, tu ne resterais pas prisonnier de ta boucle, à "attendre", et tu pourrais faire d'autres traitements en perdant moins de cycles.

Voici la partie du code, j'ai mis des commentaires. Si tu as un peu de temps, tu pourrais m'expliquer ?


Code ASM :
ld   a,[VAR_TIMING] ;charge a avec une valeur de prédéfinie
   ld   b,a  ;charge b avec cette même valeur
   ld   a,50
   sub   b      ;b est décrémenté (à quoi sert cette ligne, voir la suivante)
   ld   b,a  ;la valeur décrémentée est immédiatement détruite et remplacée par 50
   xor   a
   ld   [VAR_TIMING],a ;mise à zéro de VAR_TIMING
 
  ;
  ; pour la partie ci-dessus, je pense que ceci revient au même:
  ; ld a,50
  ; ld b,a
  ; puis éventuellement mettre à zéro VAR_TIMING (je ne sais pas à quoi ça sert)
 
  ; [EDIT] ok j'ai compris la seconde partie: DJNZ == dec B et saute si pas Z
@@time:   
   push   bc ;surle Z80 on ne peut pas empiler un registre seul, ça marche par paires.
   ;pas sur que le push/pop serve à quelque chose. Si tu veux préserver BC, il vaudrait mieux 
   ;mettre push/pop en dehors de la boucle, pour éviter de sauver/restaurer à chaque fois.
   ld   b,30
@@time2:      
   nop
   djnz   @@time2
   pop   bc
   djnz   @@time
 
   ret

Edité par Visiteur Le 17/08/2010 à 13h06
   
granced Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 09/10/2009 à 09h18

Messages: 1500

Le 17/08/2010 à 12h13
Génial l'Osaure !! En plus il y a de la musique dessus, je vais pouvoir regarder comment tu as géré le truc ! :top


MSX un jour, MSX toujours ! :D
Site web    
MSXosaure Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 03/10/2009 à 00h09

Messages: 774

Le 17/08/2010 à 12h59
pour le cross assembleur j'ai pris ASMSX.

Sub b ne décrémente pas b mais ôte la valeur b à a, en ASM Z80 toutes les opération se font sur l'accumulateur (a) , on peut aussi écrire: sub a,b.

Par contre pour le reste il faut que je regarde car c'est un peu vieux, mais c'est vrai que j'aurais bien besoin d'aide pour le timer par exemple :oups

Pour les codes ASM mettez les entre les balise de code et choisir le langage ASm (tout en bas ) même si ce n'est pas du Z80 ça fait ressortir un peu le langage.


Le MSXien le plus à l'ouest :fou ... ou presque :D
osaurer
   
KN2000 Membre non connecté

Villageois

Rang

Avatar

Inscrit le : 08/06/2010 à 09h30

Messages: 209

Le 17/08/2010 à 13h15
Pour la sous-routine, cela permet une boucle plus longue. Le registre B ne peut varier que de 0 à 255. La boucle d'attente serait un peu courte.
Au minimum, la solution de MSXOsaure permet une attente d'une trentaine d'unité de temps et au maximum, une attente de 256 fois une trentaine de cette même unité de temps.
Exemple : si on appelle la routine avec B=2, la routine va faire 3x31 boucles = 93 boucles.
(Il y a moyen d'avoir la durée en secondes mais ça demande de retrouver la durée d'un NOP + celle d'un DJNZ lorsque la condition est vraie + la durée de l'instruction LD B,n...) Edité par KN2000 Le 17/08/2010 à 13h18


Nous sommes en 2010 aps JC, toute la Gaule est envahie. Ah ben non, apparement, un village résiste encore aux envahisseurs Personalcomputerum et autres Consoledessalum. Bienvenue dans l'antre du emessix !
   
Visiteur

Vagabond

Rang

Avatar

Message : 0

Le 17/08/2010 à 13h17
Code ASM :
 
 
   ld   a,[VAR_TIMING] 
   ld   b,a  
   ld   a,50
   sub   b  
   ld   b,a  
   xor   a
   ld   [VAR_TIMING],a 
 
 


Pourrait donc être réécri ainsi ?

Code ASM :
 
 
   ld   a,[VAR_TIMING] 
   sub 50  ;si j'ai bien compris on peut passer une valeur immédiate
   ld  b,a
   xor a
   ld [VAR_TIMING],a
 
 


Edit pour KN2000 : ok, j'ai compris pour le push/pop. Merci. Edité par Visiteur Le 17/08/2010 à 13h21
   
KN2000 Membre non connecté

Villageois

Rang

Avatar

Inscrit le : 08/06/2010 à 09h30

Messages: 209

Le 17/08/2010 à 13h23
Je vote OUI pour Venom.:top


Nous sommes en 2010 aps JC, toute la Gaule est envahie. Ah ben non, apparement, un village résiste encore aux envahisseurs Personalcomputerum et autres Consoledessalum. Bienvenue dans l'antre du emessix !
   
MSXosaure Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 03/10/2009 à 00h09

Messages: 774

Le 17/08/2010 à 13h52
Oui Venom c'est plus direct et donc plus rapide/économique, je ne suis pas encore familier de l'ASM Z80 et j'ai parfois tendance à prendre des détours inutiles. Ce ne doit pas être le seul endroit où il y a ce genre d'erreur.

Si vous voulez reprendre le programme pour vous amuser, n'hésitez pas!


Le MSXien le plus à l'ouest :fou ... ou presque :D
osaurer
   
granced Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 09/10/2009 à 09h18

Messages: 1500

Le 17/08/2010 à 14h13
Je sais bien que je te demande quelque chose qui te prendra sans doute du temps, mais pourrais-tu faire un pas-à-pas de ton code (un peu comme j'avais fait pour le déplacement de sprite) ?

Je le lis depuis un moment bientôt et il y a des zones assez obscures pour moi...


MSX un jour, MSX toujours ! :D
Site web    
MSXosaure Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 03/10/2009 à 00h09

Messages: 774

Le 17/08/2010 à 14h31
C'est en projet, mais là je pars en vacances il faudra attendre la rentrée!

Sinon tu poses des questions et des personnes un peu plus calées que moi te répondront :D


Le MSXien le plus à l'ouest :fou ... ou presque :D
osaurer
   
KN2000 Membre non connecté

Villageois

Rang

Avatar

Inscrit le : 08/06/2010 à 09h30

Messages: 209

Le 17/08/2010 à 15h38
Osaure : tes vacances sont annulées :lol
Plus sérieusement, faire un pas à pas de tout le programme serait fastidieux avec le risque de passer du temps sur des choses qui seraient déjà acquises.
N'étant pas plus calé que Osaure car ça fait trop longtemps que je ne pratique plus, je veux bien tenter d'éclaircir les points que tu trouves nébuleux.;)


Nous sommes en 2010 aps JC, toute la Gaule est envahie. Ah ben non, apparement, un village résiste encore aux envahisseurs Personalcomputerum et autres Consoledessalum. Bienvenue dans l'antre du emessix !
   
granced Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 09/10/2009 à 09h18

Messages: 1500

Le 17/08/2010 à 16h02
Disons que j'ai bien saisi le principe de détournement du hook H.TIMI (en fd9fH) : tu remplaces 3 de ses 5 entrées par un saut à la routine INTERRUPTION. Mais je ne pige pas trop ce qui s'y passe ! :oups


MSX un jour, MSX toujours ! :D
Site web    
KN2000 Membre non connecté

Villageois

Rang

Avatar

Inscrit le : 08/06/2010 à 09h30

Messages: 209

Le 17/08/2010 à 16h42
:'( J'avais pas vu mais ça risque de poser problème sur un Philips (ou un Sony) du style que le lecteur de disquette ne va plus s'arrêter.
:) Lors du détournement d'un hook, il faut toujours garder son contenu initial et le remettre à la fin du programme.
Code ASM :
 
;----------------
INTERRUPTION:
;----------------
 
        push    af
        push    bc
        push    de
        push    hl
        ldhl,VAR_TIMING
        inc[hl]
        pop     hl
        pop     de
        pop     bc
        pop     af
        ret
 

Dans UFO, Osaure se sert de cette astuce pour incrémenter son compteur VAR_TIMING de façon régulière. Dans un programme, avec les conditions, l'éxécution de la boucle de ton programme demande plus ou moins de temps. Tandis que l'intervalle entre 2 interruptions est toujours identique. On évite les accélérations et les ralentissements dans le jeu.

Les PUSH servent à sauvegarder dans la "pile" les valeurs des différents registres. Et les POP à restaurer ces mêmes registres. Ici, Osaure aurait pu ne sauvegarder que HL puisque c'est le seul registre à être modifié (ld hl,VAR_TIMING). Mais c'est une bonne précaution parce que l'on a vite fait de faire un rajout et d'oublier la sauvegarde du ou des registres concernés.
Pourquoi la sauvegarde ?
En fait, au moment de l'interruption, le Z80 est dans la majorité des cas en plein "travail". Les registres contiennent des valeurs qui peuvent être indispensables. Le Z80 ne sauvegarde pas automatiquement ces valeurs : il faut donc le faire nous-même.
La pile ? Alcaline ?
Non, c'est une zone de mémoire particulière. Il faut d'ailleurs faire attention si on l'utilise beaucoup, qu'elle ne soit pas à proximité du code ou des données. J'ai un mauvais souvenir en la matière. Cette pile fonctionne comme une pile d'assiette. En suivant UFO, on pose d'abord AF, puis BC, DE et enfin HL. On modifie VAR_TIMING. Puis, POP HL, on prend donc le dessus de la pile et on le place dans HL. POP DE prend le dessus de la pile et le place dans le registre DE... Il s'agit bien de déplacements et non pas de copies.
J'insite là dessus. POP DE ne veut pas dire que l'on récupère la valeur qui était dans DE lors du PUSH DE. On fait un transfert de la pile vers le registre DE.
Par exemple : PUSH HL - PUSH DE - POP HL - POP DE. Cette suite d'instructions inverse le contenu de HL et DE (ce qui peut être souhaité par ailleurs).
Le principe de fonctionnement de la pile consiste en ceci : le dernier arrivé sera le premier sorti (LAST IN / FIRST OUT) Edité par KN2000 Le 18/08/2010 à 14h44


Nous sommes en 2010 aps JC, toute la Gaule est envahie. Ah ben non, apparement, un village résiste encore aux envahisseurs Personalcomputerum et autres Consoledessalum. Bienvenue dans l'antre du emessix !
   
Visiteur

Vagabond

Rang

Avatar

Message : 0

Le 17/08/2010 à 17h21
Ah, la variable VAR_TIMING est en réalité un delta donnant une valeur temporelle résiduelle, pendant laquelle on attend avant de recommencer les traitements ?

Si on n'a rien à faire dans un cycle complet (tracé , I/O, musique, IA ...), VAR_TIMING va être très faible (car je suppose que ça mesure l'écart entre deux intervalles temporels).

Par contre, si on a plein de trucs à faire, VAR_TIMING va s'envoler, et on aura d'autant moins à attendre.

J'imagine qu'en pseudo-code, ça donnerait ça:

lire temps_debut (disons que c'est donné en millisecondes)
faire les operations (tracé, musique...)
lire temps_fin
delta = temps_fin - temps_debut
temps_a_attendre = 1/60 - delta

1/60, c'est si on veut tourner à 60Hz

Donc 1/60, ça fait 16ms (environ)
Si les routiner prennent 6ms (donné par delta), il faut attendre (16-6) ms.

C'est ce que j'ai compris.

Au fait, pourquoi mettre VAR_TIMING à zéro dans la boucle vide ? Je suppose que cette variable est initialisée ailleurs (lecture de l'horloge avec la routine bios, au hasard ?)

Il n'y a pas moyen d'attendre la VBL une fois les opérations terminées ? C'est aussi une base assez fiable (le seul inconvénient est que ça rend les jeux injouables quand on change de pays, selon que l'on est en 50 ou 60hz)

Ca donne quoi en code MSX ? :p

EDIT: j'ai relu le post de KN2000, et ça a l'air d'être une autre technique. Un compteur qui serait incrémenté avec un tick régulier, et qui donnerait une valeur utilisée dans la boucle d'attente.
Ma "méthode" nécessite de lire deux fois l'horloge, une fois avant et une fois après les traitements d'une frame. Elle n'utilise pas les interruptions. Edité par Visiteur Le 17/08/2010 à 17h25
   
granced Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 09/10/2009 à 09h18

Messages: 1500

Le 18/08/2010 à 09h03
Donc, si je lis bien le code, VAR_TIMING (du moins le contenu de cette adresse... :oups) va s'incrémenter régulièrement (lors d'une interruption via le détournement du hook).

Mais à quelle fréquence ? Au vu du code, j'opterais pour 50 Hz, mais je n'en mettrais pas ma main à couper.

Je ne saisis d'ailleurs pas trop l'intérêt présentement d'une gestion du temps, j'aurais pensé qu'elle serait appelée pour la musique mais je n'en ai pas l'impression... :hum


MSX un jour, MSX toujours ! :D
Site web    
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie