Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 19 sur 19
  1. #1
    Invité de passage
    Inscrit en
    octobre 2009
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : octobre 2009
    Messages : 8
    Points : 0
    Points
    0

    Par défaut EMU8086, multi segmentation et buffering

    Bonjour à tous,

    Dans le cadre d'un devoir, je dois réaliser un jeu à l'aide d'EMU8086.
    J'en ai réalisé une bonne partie sans trop de soucis mais je bloque ici sur un problème qui à mon avis est très courant mais qui pourtant me fait m'arracher les cheveux.

    Pour l'affichage de mon jeu, j'ai réalisé une boucle qui affiche 25FPS.
    Cela fonctionne très bien mais le phénomène bien connu de "flickering" se produit.
    Pour le résoudre j'ai donc décidé de mettre en place un Back Buffering.
    Je voulais donc stocker cela dans un tableau de 64000 cases étant donné que je travaille en 320x200 (mode 13h).
    Mais voilà, emu8086 en a décidé autrement...

    Je me doutais bien que je ne pouvais pas stocker ce tableau dans mon segment unique de .COM
    J'ai donc décidé de créer un nouveau segment de données dédié à ce tableau.
    Mais même en faisant cela, le tableau dépasse sur le segment de code et au "blit" je me retrouve avec un joli fouilli:



    La solution aurait pu être de passer vers un .EXE mais cela a donné exactement le même résultat...

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    #make_COM#
     
     
    CSEG SEGMENT
    start:
     
    ASSUME CS:CSEG, DS:CSEG, ES:CSEG  
     
    org  100h    
     
     
    mov ah, 0   ; On passe en mode graphique.
    mov al, 13h ; mode 13h = 320x200 pixels, 256 colors.
    int 10h     ; set it!          
     
     
     
    BlitScreen:  
        pusha
     
        ;On place es dans la memoire video
        mov ax, 0A000h
        mov es, ax   
     
        ;On place ds dans le buffer video
        mov ax, DoubleBuffer
        mov ds, ax
     
        ;Addresse de depart de ds:si
        mov si, offset backBuffer  
        ;Addresse de destination de es:di
        mov di, 0 
     
        ;Nombre de tours
        mov cx,64000/2
        rep movsw 
        popa
    ret
     
    ENDS
     
    DoubleBuffer SEGMENT
     
        backBuffer db 64000 dup(0)   
     
    ENDS
    Si vous avez des retours d'expérience ou des idées pour m'aider je vous serais extrêmement reconnaissant.
    Par avance merci !

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    septembre 2007
    Messages
    5 474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2007
    Messages : 5 474
    Points : 13 994
    Points
    13 994

    Par défaut

    Je vais dire un truc bête mais as-tu pensé à mettre ton buffer à zéro avant de commencer à l'exploiter ?

  3. #3
    Invité de passage
    Inscrit en
    octobre 2009
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : octobre 2009
    Messages : 8
    Points : 0
    Points
    0

    Par défaut

    Citation Envoyé par Obsidian Voir le message
    Je vais dire un truc bête mais as-tu pensé à mettre ton buffer à zéro avant de commencer à l'exploiter ?
    Non ce n'est pas bête du tout, j'y ai pensé...
    Malheureusement une fonction aussi bete que celle-ci:

    Code :
    1
    2
    3
    4
    5
    6
    7
     
        mov ax, offset backBuffer
        mov es, ax
        xor di, di
        mov ax, 0
        mov cx, 64000/2
        rep stosw
    Ne fonctionne pas et tourne au crash à cause du dépassement de mémoire...

  4. #4
    Membre chevronné Avatar de edfed
    être humain
    Inscrit en
    décembre 2007
    Messages
    471
    Détails du profil
    Informations professionnelles :
    Activité : être humain

    Informations forums :
    Inscription : décembre 2007
    Messages : 471
    Points : 628
    Points
    628

    Par défaut

    le segment doublebuffer au lieu de l'etiquette backbuffer dans es et ça fonctionnera.

  5. #5
    Invité de passage
    Inscrit en
    octobre 2009
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : octobre 2009
    Messages : 8
    Points : 0
    Points
    0

    Par défaut

    Citation Envoyé par edfed Voir le message
    le segment doublebuffer au lieu de l'etiquette backbuffer dans es et ça fonctionnera.
    J'obtiens exactement le même résultat malheureusement.
    Dans les faits cela fonctionne déjà, ce qui doit être tracé l'est correctement, il y a juste la zone d'écriture qui se situe en plein milieu du segment de code au lieu du segment DoubleBuffer que j'ai créé pour justement servir de "poubelle".
    Ce qui fait le foulli de couleurs au fond....

    Merci pour vos réponses déjà en tous cas.

  6. #6
    Invité de passage
    Inscrit en
    octobre 2009
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : octobre 2009
    Messages : 8
    Points : 0
    Points
    0

    Par défaut

    Effectivement Obsidian, je n'avais plus vu cette erreur a force de "tentatives" hasardeuses depuis hier.
    C'est mieux comme ceci, mais cela crash toujours...
    Code :
    1
    2
    3
    4
    5
    6
    7
     
        mov ax, DoubleBuffer
        mov es, ax
        mov di, offset backBuffer
        mov ax, 0
        mov cx, 64000/2
        rep stosw

  7. #7
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    septembre 2007
    Messages
    5 474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2007
    Messages : 5 474
    Points : 13 994
    Points
    13 994

    Par défaut

    Citation Envoyé par Chdidi Voir le message
    J'obtiens exactement le même résultat malheureusement.
    Attention, il faut initialiser le registre de segment à doubleBuffer et DI à backBuffer. Cela dit, c'est déjà l'approche que tu suis dans ton tout premier exemple…

    Dans les faits cela fonctionne déjà, ce qui doit être tracé l'est correctement, il y a juste la zone d'écriture qui se situe en plein milieu du segment de code au lieu du segment DoubleBuffer que j'ai créé pour justement servir de "poubelle".
    Es-tu sûr que c'est vraiment le code que tu vois se blitter à l'écran ? Parce que :

    1. Ça représente VRAIMENT beaucoup de code, et je ne crois pas que tu en aies écrit autant jusqu'ici ;
    2. Il n'y a pas de raison que ça se produise puisque tu as alloué suffisamment de mémoire pour le buffer de backup (64000 octets exactement) ;
    3. Tes sprites sont affichés par dessus les parasites. Tu devrais écraser ton code de cette façon.

  8. #8
    Invité de passage
    Inscrit en
    octobre 2009
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : octobre 2009
    Messages : 8
    Points : 0
    Points
    0

    Par défaut

    Citation Envoyé par Obsidian Voir le message
    Es-tu sûr que c'est vraiment le code que tu vois se blitter à l'écran ? Parce que :
    1. Ça représente VRAIMENT beaucoup de code, et je ne crois pas que tu en aies écrit autant jusqu'ici ;
    2. Il n'y a pas de raison que ça se produise puisque tu as alloué suffisamment de mémoire pour le buffer de backup (64000 octets exactement) ;
    3. Tes sprites sont affichés par dessus les parasites. Tu devrais écraser ton code de cette façon.
    Il y a actuellement 1050 lignes de code, penses tu que cela puisse être autre chose ?
    Ce qui est dérangeant c'est que je n'arrive pas à "débugguer" mon code en voyant par exemple l'adresse où j'écris, car je pense que le problème c'est que le compilateur "ignore" mon segment DoubleBuffer et cale ça où il peut...

    J'ai essayé de tourner ça dans tous les sens et je n'arrive pas à effacer le contenu de backBuffer.
    Une simple loop avec un mov provoque un crash (sans erreur du dos)...
    C'est cela qui me pousse à croire à un problème de placement en mémoire

  9. #9
    Membre chevronné Avatar de edfed
    être humain
    Inscrit en
    décembre 2007
    Messages
    471
    Détails du profil
    Informations professionnelles :
    Activité : être humain

    Informations forums :
    Inscription : décembre 2007
    Messages : 471
    Points : 628
    Points
    628

    Par défaut

    utilise un autre segment vraiment externe.
    peut etre qu'il faudrait passer en format MZ pour avoir plusieurs segments au lieu d'un seul.

    ou donner l'adresse explicite du segment doublebuffer, je te conseille le segment 8000h pour ça. le segment 0A000h etant le framebuffer.

  10. #10
    Invité de passage
    Inscrit en
    octobre 2009
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : octobre 2009
    Messages : 8
    Points : 0
    Points
    0

    Par défaut

    Citation Envoyé par edfed Voir le message
    utilise un autre segment vraiment externe.
    peut etre qu'il faudrait passer en format MZ pour avoir plusieurs segments au lieu d'un seul.

    ou donner l'adresse explicite du segment doublebuffer, je te conseille le segment 8000h pour ça. le segment 0A000h etant le framebuffer.
    VICTOIRE !
    J'ai écris explicitement dans le segment 07000h mon buffer et tout fonctionne parfaitement !
    Je peux écrire, effacer, copier et lire sans soucis.
    Le 08000h provoquait encore quelques artéfacts.
    Cela fait un peu "bidouille", je regarderai donc pour la première solution que tu m'as donné histoire de rendre cela plus propre.
    Il a aussi fallu que je passe à un format .EXE pour pouvoir changer ds en cours d'execution, en .COM il y avait crash...

    Encore merci à vous deux, bonne soirée !

  11. #11
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    septembre 2007
    Messages
    5 474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2007
    Messages : 5 474
    Points : 13 994
    Points
    13 994

    Par défaut

    Euh ! Il y a deux choses quand même qui me sautent aux yeux ce matin :

    1. Tu n'initialises pas ton segment de pile ! En *.com, elle devrait être au même endroit que ton segment de code, mais il faudrait voir si ce n'est pas elle que tu écrases ;
    2. Tu ne fixes pas le sens de déplacement de STOSW avec CLD ou STD !


    Si ton blit est parti dans le mauvais sens, c'est pas étonnant que tu aies écrasé ton code. :-)

  12. #12
    Invité de passage
    Inscrit en
    octobre 2009
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : octobre 2009
    Messages : 8
    Points : 0
    Points
    0

    Par défaut

    Citation Envoyé par Obsidian Voir le message
    Euh ! Il y a deux choses quand même qui me sautent aux yeux ce matin :

    1. Tu n'initialises pas ton segment de pile ! En *.com, elle devrait être au même endroit que ton segment de code, mais il faudrait voir si ce n'est pas elle que tu écrases ;
    2. Tu ne fixes pas le sens de déplacement de STOSW avec CLD ou STD !


    Si ton blit est parti dans le mauvais sens, c'est pas étonnant que tu aies écrasé ton code. :-)
    J'ai fait un nouvel essai, le blit part bien dans le bon sens...
    Pour la pile, c'est possible, mais je ne sais pas comment vérifier cela.
    J'espère juste qu'en mémoire il n'y a rien à l'adresse 07000h qui soit critique, si ce n'est pas le cas je pense rester sur ce stockage...

  13. #13
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    septembre 2007
    Messages
    5 474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2007
    Messages : 5 474
    Points : 13 994
    Points
    13 994

    Par défaut

    Citation Envoyé par Chdidi Voir le message
    J'ai fait un nouvel essai, le blit part bien dans le bon sens...
    Oui, mais c'est purement aléatoire. Ça dépend de l'état du bit juste avant que ton programme soit appelé. Est-ce que ça plante toujours même si ça part dans le bon sens ?

    Pour la pile, c'est possible, mais je ne sais pas comment vérifier cela.
    J'espère juste qu'en mémoire il n'y a rien à l'adresse 07000h qui soit critique, si ce n'est pas le cas je pense rester sur ce stockage...
    Je n'ai plus le plan mémoire exact des PC 8086 en mode réel, mais si tu travailles sous D.O.S., le mieux serait quand même de lui réclamer officiellement un segment libre avec une fonction d'allocation.

  14. #14
    Invité de passage
    Inscrit en
    octobre 2009
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : octobre 2009
    Messages : 8
    Points : 0
    Points
    0

    Par défaut

    Citation Envoyé par Obsidian Voir le message
    Oui, mais c'est purement aléatoire. Ça dépend de l'état du bit juste avant que ton programme soit appelé. Est-ce que ça plante toujours même si ça part dans le bon sens ?

    Je n'ai plus le plan mémoire exact des PC 8086 en mode réel, mais si tu travailles sous D.O.S., le mieux serait quand même de lui réclamer officiellement un segment libre avec une fonction d'allocation.
    Oui j'ai testé avec CLD, cela plante toujours...
    Est-ce que tu aurais des liens sur les fonctions d'allocation ?
    Je n'ai aucune idée de comment faire ça...

    Merci

  15. #15
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    septembre 2007
    Messages
    5 474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2007
    Messages : 5 474
    Points : 13 994
    Points
    13 994

    Par défaut

    Citation Envoyé par Chdidi Voir le message
    Oui j'ai testé avec CLD, cela plante toujours...
    Ce qui est curieux, c'est que ça plante avec un *.exe. C'est probablement dû à plusieurs problèmes cumulés. Par contre, avec un *.com, c'est normal : c'est un programme fait pour tenir un seul segment, donc maximum 65280 octets, code, données et pile compris. Mais c'est surtout un fichier-image sans aucune structure et chargé tel quel en mémoire à partir de l'offset 100h.

    Donc, il n'y aucune raison pour que le fichier exécutable ait en lui-même une idée de l'endroit où placer « doubleBuffer », étant donné que le segment de code est alloué par le système au chargement et qu'il n'y a pas de table associée à ton fichier pour boucher les trous comme il y en a avec l'exe.

    Il y a donc de fortes chances pour « doubleBuffer », à la compilation, vaille soit zéro, soit tombe sur le premier multiple de 16 octets libre après la taille de ton code. Dans les deux cas, tu écrases les vecteurs de tes interruptions en début de plan mémoire.

    Est-ce que tu aurais des liens sur les fonctions d'allocation ?
    Je n'ai aucune idée de comment faire ça...
    Regarde les fonctions 48h (allouer) et 49h (libérer) de l'interruption 21h :

    http://www.gladir.com/LEXIQUE/INTR/int21f48.htm

    Tu alloues ta mémoire par « paragraphes », c'est-à-dire par blocs multiples de 16 octets (ce qui correspond en réalité exactement à « l'unité » d'un registre de segment).

  16. #16
    Membre Expert
    Avatar de Forthman
    Homme Profil pro François
    conception mécanique
    Inscrit en
    janvier 2005
    Messages
    508
    Détails du profil
    Informations personnelles :
    Nom : Homme François
    Âge : 39
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : conception mécanique
    Secteur : Industrie

    Informations forums :
    Inscription : janvier 2005
    Messages : 508
    Points : 1 119
    Points
    1 119

    Par défaut

    on peut aussi utiliser plus d'un segment avec un fichier .COM

    Je pencherai plutôt pour la fonction 4Ah de l'int 21h
    pour "modifier" l'allocation mémoire (je l'utilisais souvent sur avec mes programmes DOS)

    Code :
    1
    2
    3
    4
    En entrée :
    ES = segment de base ( =CS pour un .COM)
    BX = nombre de paragraphes à réserver
    AH= 4Ah
    En sortie :
    si FC=1 alors erreur et AX = code d'erreur

    Par exemple, pour réserver 64Ko de plus aux 64Ko du programme .COM

    Code :
    1
    2
    3
    4
    5
    mov ax,cs
    mov es,ax
    mov bx,2000h (8192*16=131072octets = 128Ko)
    mov ah,4Ah
    int 21h
    Tu peux après initialiser es pour pointer sur ton segment "graphique" par

    Code :
    1
    2
    3
    mov ax,cs
    add ax,1000h
    mov es,ax
    a+ François

  17. #17
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    septembre 2007
    Messages
    5 474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2007
    Messages : 5 474
    Points : 13 994
    Points
    13 994

    Par défaut

    Citation Envoyé par Forthman Voir le message
    on peut aussi utiliser plus d'un segment avec un fichier .COM
    Oui, mais à condition de l'allouer explicitement à l'exécution. C'est ce que l'on dit ici.

    Je pencherai plutôt pour la fonction 4Ah de l'int 21h
    pour "modifier" l'allocation mémoire (je l'utilisais souvent sur avec mes programmes DOS)
    Bof, je ne la trouve pas si « intéressante » que ça dans le contexte actuel car le primo-postant a besoin de 64000 octets pour son double buffer, soit presque exactement la taille adressable d'un segment. En plus mélanger le code et tenir compte l'emplacement actuelle de la pile, c'est se donner du mal pas grand chose. En plus, la fonction en question ne peut pas déplacer le segment au besoin. Donc, s'il a la malchance d'être immédiatement suivi d'un objet en mémoire, la réallocation ne pourra pas se faire.

  18. #18
    Membre chevronné Avatar de edfed
    être humain
    Inscrit en
    décembre 2007
    Messages
    471
    Détails du profil
    Informations professionnelles :
    Activité : être humain

    Informations forums :
    Inscription : décembre 2007
    Messages : 471
    Points : 628
    Points
    628

    Par défaut

    pour faire tourner un programme en stand alone, on peut utiliser le segment 9000h sans se preoccuper de ce qu'il peut bien y avoir dedans. en mode purement reel, la zone entre 10000h et 9FFFFh est largement disponible. sur un systeme où seul sera chargé ce programme, il n'y aura pas le moindre probleme à allouer de force certaines zones de mémoire. vu qu'emu8086 est un emulateur, il n'y a aucun probleme à tester. puis le probleme est assez simple en verité. il va pas tarder à être resolu je pense.

  19. #19
    Membre Expert
    Avatar de Forthman
    Homme Profil pro François
    conception mécanique
    Inscrit en
    janvier 2005
    Messages
    508
    Détails du profil
    Informations personnelles :
    Nom : Homme François
    Âge : 39
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : conception mécanique
    Secteur : Industrie

    Informations forums :
    Inscription : janvier 2005
    Messages : 508
    Points : 1 119
    Points
    1 119

    Par défaut

    bourrin va !

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •