Taches de Martin

Partagez votre expérience de PureBasic avec les autres utilisateurs.
filperj
Messages : 395
Inscription : jeu. 22/janv./2004 1:13

Taches de Martin

Message par filperj »

Je suis tombé sur l'algo des taches de Martin en fouinant dans l'excellent site d'Opie Pécheux: http://opecheux.free.fr/

C'est tout simple: l'écran est représenté par un tableau bidimensionnel d'octets (en mode 256 couleurs). A chaque boucle d'affichage, on parcourt tout le tableau et, pour chaque pixel, on fait la moyenne entre les valeurs de ses 4 voisins (dessus, dessous, gauche, droite), on ajoute 1 à cette moyenne et on attribue la valeur obtenue au pixel.

Autrement dit, à chaque boucle, pour chaque pixel:
pix(x,y)=(pix(x,y-1)+pix(x-1,y)+pix(x+1,y)+pix(x,y+1))/4+1

Enfantin, non? Et ça fait ça:
(Il faut activer l'assembleur en ligne dans les options de compilation - l'assembleur n'est pas vraiment de l'optimisation, c'est plutôt que j'ai eu la flemme de traduire le code originel en PB)

Code : Tout sélectionner


Global _virtuscr.l

#largeur=640 : #hauteur=480   ;dimensions de l'écran
!largeur=640                  ;les mêmes pour Fasm
!hauteur=480


Enumeration
   #rougebleujaune
   #nivgris
   #defaut
EndEnumeration

;#modepalette=#rougebleujaune
#modepalette=#nivgris
;#modepalette=#defaut

CompilerIf #modepalette=#defaut
   
   Procedure palettiser()
   EndProcedure
   
  CompilerElse
   
   Procedure palettiser()
      
      InitPalette()
      
      CreatePalette(0)
      
      CompilerSelect #modepalette
         
         CompilerCase #rougebleujaune
            
            For t=0 To 63
               SetPaletteColor(t,RGB(t*4,0,0))
               SetPaletteColor(t+64,RGB((63-t)*4,0,t*4))
               SetPaletteColor(t+128,RGB(t*4,t*4,(63-t)*4))
               SetPaletteColor(t+192,RGB(255,255,t*4))
            Next
            
         CompilerCase #nivgris
         
            For t=0 To 255
               SetPaletteColor(t,RGB(t,t,t))
            Next
         
      CompilerEndSelect
      
      DisplayPalette(0)
      
   EndProcedure
   
CompilerEndIf




Procedure onattend()
   
   Repeat
      Delay(80)
      FlipBuffers()
   Until IsScreenActive()
   
EndProcedure



Procedure rendu()
   
   scraoutpout=ScreenOutput()
   If scraoutpout : If StartDrawing(scraoutpout)
      
      dbuff=DrawingBuffer()
      pitch=DrawingBufferPitch()
      
      If pitch=#largeur
         
         CopyMemory(_virtuscr,dbuff,#largeur*#hauteur)
         
        Else
         
         For ligne=0 To #hauteur-1
            CopyMemory(_virtuscr+ligne*#largeur,dbuff+ligne*pitch,#largeur)
         Next
         
      EndIf
      
   StopDrawing() : EndIf : EndIf
   
EndProcedure




Enumeration
   #bordsnoirs
   #bordsjoints
EndEnumeration

#modedesbords=#bordsnoirs
;#modedesbords=#bordsjoints

Procedure martinet()
   
   DisableDebugger   ;le débogueur fout le bordel dans les "LOOP"
   
   CompilerSelect #modedesbords
      
      CompilerCase #bordsjoints
         
         MOV edi,_virtuscr
         XOR ebx,ebx
         CLD
         MOVZX ax,byte[edi+largeur*(hauteur-1)]
         MOV bl,[edi+largeur*hauteur-1]
         ADD ax,bx
         MOV bl,[edi+1]
         ADD ax,bx
         MOV bl,[edi+largeur]
         ADD ax,bx
         SHR ax,2
         INC al
         !stosb
         MOV ecx,largeur-1
         lign0:
           MOVZX ax,byte[edi+largeur*(hauteur-1)]
           MOV bl,[edi-1]
           ADD ax,bx
           MOV bl,[edi+1]
           ADD ax,bx
           MOV bl,[edi+largeur]
           ADD ax,bx
           SHR ax,2
           INC al
           !stosb
           LOOP l_lign0
         MOV ecx,largeur*(hauteur-2)
         centrecr:
           MOVZX ax,byte[edi-largeur]
           MOV bl,[edi-1]
           ADD ax,bx
           MOV bl,[edi+1]
           ADD ax,bx
           MOV bl,[edi+largeur]
           ADD ax,bx
           SHR ax,2
           INC al
           !stosb
           LOOP l_centrecr
         MOV ecx,largeur-1
         derlign:
           MOVZX ax,byte[edi-largeur]
           MOV bl,[edi-1]
           ADD ax,bx
           MOV bl,[edi+1]
           ADD ax,bx
           MOV bl,[edi-largeur*(hauteur-1)]
           ADD ax,bx
           SHR ax,2
           INC al
           !stosb
           LOOP l_derlign
         MOVZX ax,byte[edi-largeur]
         MOV bl,[edi-1]
         ADD ax,bx
         MOV bl,[edi+1-largeur*hauteur]
         ADD ax,bx
         MOV bl,[edi-largeur*(hauteur-1)]
         ADD ax,bx
         SHR ax,2
         INC al
         !stosb
         
      CompilerCase #bordsnoirs
         
         MOV edi,_virtuscr
         ADD edi,largeur+1
         MOV edx,hauteur-2    
         XOR ebx,ebx
         CLD
         bclecr:
           MOV ecx,largeur-2
           bcllign:
             MOVZX ax,byte[edi-largeur]
             MOV bl,[edi-1]
             ADD ax,bx
             MOV bl,[edi+1]
             ADD ax,bx
             MOV bl,[edi+largeur]
             ADD ax,bx
             SHR ax,2
             INC al
             !stosb
             LOOP l_bcllign
           ADD edi,2
           DEC edx
           JNZ l_bclecr
         
   CompilerEndSelect
   
   EnableDebugger
   
EndProcedure



;-ZHE PROG



If InitKeyboard() And InitSprite() And OpenScreen(#largeur,#hauteur,8,"Taches de Martin")

   palettiser()
   
   _virtuscr=AllocateMemory(#largeur*#hauteur)
   
   SetFrameRate(25)
   
   Repeat
      
      martinet()
      
      rendu()
      
      ExamineKeyboard()
      
      FlipBuffers()
      
      If IsScreenActive()=0
         onattend()
      EndIf
      
   Until KeyboardReleased(#pb_key_escape)

   
  Else
   
   MessageRequester("Ah ben ça marche pas.","Impossible d'initialiser DirectX7")
   
EndIf
Le chaos l'emporte toujours sur l'ordre
parcequ'il est mieux organisé.
(Ly Tin Wheedle)
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

C'est joli

J'ai essayé en mettant un peu de couleur

Code : Tout sélectionner

  For t=0 To 255 
    SetPaletteColor(t,RGB(255-t,255-t,0)) 
  Next 
ça pourrait faire un joli screensaver :)
filperj
Messages : 395
Inscription : jeu. 22/janv./2004 1:13

Message par filperj »

Ben et tout mes compilerif, alors? :lol:
Il suffit de changer la valeur de la constante #modepalette.
Esaie de lui donner la valeur "#defaut", chez moi ça donne un truc kitchissime.

Et au fait, un tableau d'octets ça peut aussi représenter une heightmap, non?
Ca pourrai être rigolo :D
Le chaos l'emporte toujours sur l'ordre
parcequ'il est mieux organisé.
(Ly Tin Wheedle)
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

ah oui je n'avais pas vu , c'est encore mieux comme ça :)

quand tu parles de heightmap c'est une image ?

J'allais te le dire ,ça serait bien de le faire avec une image pour voir :)
fweil
Messages : 505
Inscription : dim. 16/mai/2004 17:50
Localisation : Bayonne (64)
Contact :

Message par fweil »

é tt mignon ce truc ...
Mon avatar reproduit l'image de 4x1.8m présentée au 'Salon international du meuble de Paris' en janvier 2004, dans l'exposition 'Shades' réunisant 22 créateurs autour de Matt Sindall. L'original est un stratifié en 150 dpi.
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

c'est pas mal du out, extra, je dirais même, j'adore l'effet que ça produit :)
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

a mi-chemin entre Magma et comportement Chaotique, j'adore !

Bravo .. :D (un extincteur de plus ?? ) :D
filperj
Messages : 395
Inscription : jeu. 22/janv./2004 1:13

Message par filperj »

C'est à Martin qu'il faut dire Bravo!
Bon tout à l'heure j'essaierai d'initialiser le tableau avec une image.
Le chaos l'emporte toujours sur l'ordre
parcequ'il est mieux organisé.
(Ly Tin Wheedle)
filperj
Messages : 395
Inscription : jeu. 22/janv./2004 1:13

Message par filperj »

Bon voilà, j'ai initialisé avec une image.
Mais en fait, Bah... Aucun interrêt!
L'image se dissout rapidement dans la mousse, et on en entend plus parler :cry:

Code : Tout sélectionner


UseJPEGImageDecoder() : UsePNGImageDecoder()

Global _virtuscr.l,_image.s

#largeur=640 : #hauteur=480   ;dimensions de l'écran
!largeur=640                  ;les mêmes pour Fasm
!hauteur=480


Enumeration
   #rougebleujaune
   #nivgris
   #defaut
   #bleurose
EndEnumeration

;#modepalette=#rougebleujaune
#modepalette=#nivgris
;#modepalette=#defaut
;#modepalette=#bleurose

CompilerIf #modepalette=#defaut
   
   Procedure palettiser()
   
      InitPalette()
      If LoadPalette(0,_image)
         DisplayPalette(0)
      EndIf
      
   EndProcedure
   
  CompilerElse
   
   Procedure palettiser()
      
      InitPalette()
      
      If LoadPalette(0,_image)
         DisplayPalette(0)
         ProcedureReturn
      EndIf
      
      CreatePalette(0)
      
      DisplayPalette(0)
      
      CompilerSelect #modepalette
         
         CompilerCase #rougebleujaune
            
            For t=0 To 63
               SetPaletteColor(t,RGB(t*4,0,0))
               SetPaletteColor(t+64,RGB((63-t)*4,0,t*4))
               SetPaletteColor(t+128,RGB(t*4,t*4,(63-t)*4))
               SetPaletteColor(t+192,RGB(255,255,t*4))
            Next
            
         CompilerCase #nivgris
         
            For t=0 To 255
               SetPaletteColor(t,RGB(t,t,t))
            Next
         
         CompilerCase #bleurose
            
            For t=0 To 255
               SetPaletteColor(t,RGB(t,t/2,t/2+128))
            Next
            
      CompilerEndSelect
      
      DisplayPalette(0)
      
   EndProcedure
   
CompilerEndIf




Procedure onattend()
   
   Repeat
      Delay(80)
      FlipBuffers()
   Until IsScreenActive()
   
EndProcedure



; Procedure rendu()
;    
;    scraoutpout=ScreenOutput()
;    If scraoutpout : If StartDrawing(scraoutpout)
;       
;       dbuff=DrawingBuffer()
;       pitch=DrawingBufferPitch()
;       
;       If pitch=#largeur
;          
;          CopyMemory(_virtuscr,dbuff,#largeur*#hauteur)
;          
;         Else
;          
;          For ligne=0 To #hauteur-1
;             CopyMemory(_virtuscr+ligne*#largeur,dbuff+ligne*pitch,#largeur)
;          Next
;          
;       EndIf
;       
;    StopDrawing() : EndIf : EndIf
;    
; EndProcedure




Enumeration
   #bordsnoirs
   #bordsjoints
EndEnumeration

#modedesbords=#bordsnoirs
;#modedesbords=#bordsjoints

Procedure martinet()
   
   DisableDebugger   ;le débogueur fout le bordel dans les "LOOP"
   
   CompilerSelect #modedesbords
      
      CompilerCase #bordsjoints
         
         MOV edi,_virtuscr
         XOR ebx,ebx
         CLD
         MOVZX ax,byte[edi+largeur*(hauteur-1)]
         MOV bl,[edi+largeur*hauteur-1]
         ADD ax,bx
         MOV bl,[edi+1]
         ADD ax,bx
         MOV bl,[edi+largeur]
         ADD ax,bx
         SHR ax,2
         INC al
         !stosb
         MOV ecx,largeur-1
         lign0:
           MOVZX ax,byte[edi+largeur*(hauteur-1)]
           MOV bl,[edi-1]
           ADD ax,bx
           MOV bl,[edi+1]
           ADD ax,bx
           MOV bl,[edi+largeur]
           ADD ax,bx
           SHR ax,2
           INC al
           !stosb
           LOOP l_lign0
         MOV ecx,largeur*(hauteur-2)
         centrecr:
           MOVZX ax,byte[edi-largeur]
           MOV bl,[edi-1]
           ADD ax,bx
           MOV bl,[edi+1]
           ADD ax,bx
           MOV bl,[edi+largeur]
           ADD ax,bx
           SHR ax,2
           INC al
           !stosb
           LOOP l_centrecr
         MOV ecx,largeur-1
         derlign:
           MOVZX ax,byte[edi-largeur]
           MOV bl,[edi-1]
           ADD ax,bx
           MOV bl,[edi+1]
           ADD ax,bx
           MOV bl,[edi-largeur*(hauteur-1)]
           ADD ax,bx
           SHR ax,2
           INC al
           !stosb
           LOOP l_derlign
         MOVZX ax,byte[edi-largeur]
         MOV bl,[edi-1]
         ADD ax,bx
         MOV bl,[edi+1-largeur*hauteur]
         ADD ax,bx
         MOV bl,[edi-largeur*(hauteur-1)]
         ADD ax,bx
         SHR ax,2
         INC al
         !stosb
         
      CompilerCase #bordsnoirs
         
         MOV edi,_virtuscr
         ADD edi,largeur+1
         MOV edx,hauteur-2    
         XOR ebx,ebx
         CLD
         bclecr:
           MOV ecx,largeur-2
           bcllign:
             MOVZX ax,byte[edi-largeur]
             MOV bl,[edi-1]
             ADD ax,bx
             MOV bl,[edi+1]
             ADD ax,bx
             MOV bl,[edi+largeur]
             ADD ax,bx
             SHR ax,2
             INC al
             !stosb
             LOOP l_bcllign
           ADD edi,2
           DEC edx
           JNZ l_bclecr
         
   CompilerEndSelect
   
   EnableDebugger
   
EndProcedure


Procedure choisimage()
   
   _image=OpenFileRequester("Martin","","fichiers images|*.bmp;*.dib;*.png;*.jpg;*.jpeg",0)
   If _image="" Or LoadImage(0,_image)=0 : End : EndIf
   
EndProcedure





Procedure initecran()
   
   CreateSprite(0,#largeur,#hauteur,#pb_sprite_memory)
   
   StartDrawing(SpriteOutput(0))
      
      _virtuscr=DrawingBuffer()
      DrawImage(UseImage(0),0,0,#largeur,#hauteur)
      
   StopDrawing()
   
   FreeImage(0)
   
EndProcedure







;-ZHE PROG

choisimage()


If InitKeyboard() And InitSprite() And OpenScreen(#largeur,#hauteur,8,"Taches de Martin")

   palettiser()
   
   INitecran()
   
   SetFrameRate(25)
   
   Repeat
      
      martinet()
      
      ;rendu()
      DisplaySprite(0,0,0)
      
      ExamineKeyboard()
      
      FlipBuffers()
      
      If IsScreenActive()=0
         onattend()
      EndIf
      
   Until KeyboardReleased(#pb_key_escape)

   
  Else
   
   MessageRequester("Ah ben ça marche pas.","Impossible d'initialiser DirectX7")
   
EndIf
Bon tant pis.
Le chaos l'emporte toujours sur l'ordre
parcequ'il est mieux organisé.
(Ly Tin Wheedle)
fweil
Messages : 505
Inscription : dim. 16/mai/2004 17:50
Localisation : Bayonne (64)
Contact :

Message par fweil »

Ben moi je vous ai fait ça pour broder un peu autour des tâches et de l'assembleur ...

Code : Tout sélectionner

;
; Small ASM tutorial
; Petit TUT ASM
;
; F.Weil 20040617
;
; This listing is a workshop about ASM insertion in PureBasic code. Nothing exhaustive but a possible first basis.
;
; The workshop is based on 'les taches de Martin', meaning each point of an image is set according to the average of it's neighbors.
; A limited color palette is necessary to render appropriate effect.
;
; I propose to use a regular 32 bits depth for the screen and to solve this by calculating the final color of each point.
;
; Focus is made on how to address the drawing buffer directly.
;
; Purpose of this workshop is not to show that it is possible to do much better than PureBasic as it demonstrates the opposite.
; Only in some cases using ASM will help, but most of the time not. This workshop shows how to code in PureBasic well, and how
; few improvements can be obtained using ASM coding.
;
; For a better user experience, it is possible to parse methods execution by using left / right keyboard arrows, and to change
; drawing area size using NumPad4 / NumPad6
;
; The algorithm name, frames per second obtained and drawing size are displayed in real time.
;================================================================================
; Ce listing a pour but de montrer comment étudier la transposition en ASM de certaines parties de code.
; Rien d'exhaustif mais une prise en main qui peut donner de bonnes bases.
;
; Reprise du principe des taches de Martin
;
; Là j'ai mis l'accent sur la gestion directe du DrawingBuffer
;
; L'algorithme proposé est de même principe que celui d'origine pour les taches de Martin, c'est à dire
; pour chaque point P(X, Y) on associe une couleur calculée à partir de la moyenne des couleurs des 4 points
; voisins + 1
; Soit couleur(P(X, Y)) = (couleur(P1(X, Y - 1)) + couleur(P2(X - 1, Y)) + couleur(P3(X + 1, Y)) + couleur(P4(X, Y + 1))) / 4 + 1
;
; Pour rendre l'effet escompté on doit travailler dans une palette limitée.
;
; Pour faire les choses sans passer par un screen en 8 bits ou autre chose, je prends le mode par défaut de l'écran en 32 bits, et
; je convertis en recalculant couleur
;
; couleur = couleur % 64 + 192
; couleur = couleur << 10 + couleur
;
; Le but de cette démonstration ne consiste pas à montrer des carences de PureBasic, bien au contraire. Il ressort que l'utilisation de l'ASM
; n'apporte que peu d'améliorations si le codage PureBasic est bien conçu par le développeur.
;
; Pour une meilleure expérimentation des méthodes ici, il est possible de naviguer sur les différents types de code en utilisant les
; flèches gauche / droite du clavier et de changer la taille de la zone de dessin avec les touches 4 / 6 du clavier numérique.
;
; Un affichage temps réel de l'algorithme utilisé, du nombre de trames par seconde et de la taille du dessin est effectué.
;

; This enumeration is made to make the different codes to executes easier to access
; Also the codes names are placed in strings to display stats
;
; Cette énumération est mise en place pour rendre l'accès aux différents algorithmes plus aisés.
; Les noms des codes à exécuter sont également placés dans un tableau de chaînes pour l'affichage des stats.

;
; Here is a chart of experimental results (inFPS) I found on my design PC
; Voici un tableau des résultats expérimentaux (en FPS) obtenus sur mon PC de développement
;
; FlipBuffers(1)                        128x128    256x256    320x240    480x360    640x480    800x600
; PureBasic_Regular_Code             4              2               1              -                -              -
; PureBasic_Better_Code             60             30             30            21              10             8
; PureBasic_Optimized_Code       60             30             30            22              10             8
; PureBasic_LowLevel_Code        60             30             30            22              10             8
; PureBasic_Chewed_Code          60             30             30            19                9             7
; ASM_Code                               60             30             30            23              10             8
; PureBasic_LowLevel_Code2       60             59             59            45              20           15
; ASM_LowLevel_Code2              60             60             59             50              22           16
;       
; FlipBuffers(0)                        128x128    256x256    320x240    480x360    640x480    800x600
; PureBasic_Regular_Code             5              2               1              -                -              -
; PureBasic_Better_Code            260            55             46            21              12              8
; PureBasic_Optimized_Code       251            50             49           22               11              8
; PureBasic_LowLevel_Code        251            50             49           22               11              8
; PureBasic_Chewed_Code         216            44             42            19              10              7
; ASM_Code                              255            55             52            23              12              9
; PureBasic_LowLevel_Code2      604          126            100           45              27             17
; ASM_LowLevel_Code2              627          143            113           51              30             20
; 
; Results measured on my 1.2GHz / 32MB graphic PC
; Résultats mesurés sur mon PC 1,2GHz / Graphique 32MO
; 

Enumeration
  #PureBasic_Regular_Code
  #PureBasic_Better_Code
  #PureBasic_Optimized_Code
  #PureBasic_LowLevel_Code
  #PureBasic_Chewed_Code
  #ASM_Code
  #PureBasic_LowLevel_Code2
  #ASM_LowLevel_Code2
EndEnumeration

#LastCode = #ASM_LowLevel_Code2

Global tz.l, FPS.l, NFrames.l, AFrames.l, TFrames.l ; Stats

;
; ResetAll allows to clear the screen's buffers and thearrays used in the program
; ResetAll permet d'effacer les buffers et de remettre les tableaux utilisés à zéro.
Procedure ResetAll()
  FlipBuffers(1)
  ClearScreen(0, 0, 0)
  FlipBuffers(1)
  ClearScreen(0, 0, 0)
  Dim DrawingArray.l(1024, 768)
  Dim DrawingArea.l(1024 * 768)
  tz = ElapsedMilliseconds()
  FPS = 0
  NFrames = 0
  AFrames = 0
  TFrames = 0
EndProcedure

ExecuteCode = #ASM_Code

Dim CodeType.s(10)
Dim DrawingWidth.l(10)
Dim DrawingHeight.l(10)

; A list of code parts names is placed in the DataSection
; Une liste des noms des parties du code est placée en DataSection.
For i = 0 To #LastCode
  Read CodeType(i)
  CodeType(i) + Space(40 - Len(CodeType(i)))
Next

LastSize = 5
WidthHeight = 3

; A list of drawing sizes is placed in DataSection
; Une liste des tailles de zone de dessin est donnée en DataSection
For i = 0 To LastSize
  Read DrawingWidth(i)
  Read DrawingHeight(i)
Next

;
; DrawingArray is a 2 dimensions array to store screen's x, y pixels in some part of the program
; DrawingArea is a single dimension array used in the same purpose in some other parts
;
; DrawinArray est un tableau à 2 dimensions utilisé pour mémoriser les pixels x, y de l'écran dans certaines parties du programme
; DrawingArea est un tableau à une seule dimension utilisé dans le même but, mais dans d'autres parties.
;
Dim DrawingArray.l(1024, 768)
Dim DrawingArea.l(1024 * 768)

; The current drawing width and heigth are set and xTop, yTop, xBottom, yBottom are bounds
; La largeur et la hauteur courante pour le dessin sont initalisées ainsi que les limites xTop, yTop, xBottom, yBottom
DrawingWidth = DrawingWidth(WidthHeight)
DrawingHeight = DrawingHeight(WidthHeight)
ScreenXSize = GetSystemMetrics_(#SM_CXSCREEN)
ScreenYSize = GetSystemMetrics_(#SM_CYSCREEN)
xTop = (ScreenXSize - DrawingWidth) / 2 + 1
yTop = (ScreenYSize - DrawingHeight) / 2 + 1
xBottom = xTop + DrawingWidth - 2
yBottom = yTop + DrawingHeight - 2

;
;
;
  If InitKeyboard() And InitSprite() And OpenScreen(ScreenXSize, ScreenYSize, 32, "Taches de Matin") 
      StartDrawing(ScreenOutput())
        DrawingFont(LoadFont(23, "Verdana", 8, #PB_Font_HighQuality | #PB_Font_Bold))
      StopDrawing()
      Repeat 
        ;
        ; FlipBuffers is used with two possible argument value : 0 without buffer buffer sync which is shorter but
        ; may generate more flickering on the screen, or 1 to wait the buffer ready before to display it.
        ;
        ; Mode change is accesible using up / down arrows
        ;=========================================================================
        ; On utilise la commande FlipBuffers(0) (sans synchronisation plus rapide mais qui peut produire des scintillements
        ; ou FlipBuffers(1) qui attend que le buffer soit prêt avant affichage.
        ;
        ; Le changement de mode se fait en appuyant les flèches haut ou bas.
        ;
        FlipBuffers(FlipBuffers)
        StartDrawing(ScreenOutput())
          Select ExecuteCode
            ;
            ; To start the following code just do what the top comments describe, using Point(x, y) to know a pixel value. Neighbors are
            ; injected in a formula and the given point set using Plot.
            ;=====================================================================================
            ; Pour commencer voici dans une écriture conventionnelle le code correspondant à la spécification donnée en commentaire ci-dessus.
            ;
            ; Pour l'ensemble des points à traiter, on calcule la somme des valeurs des 4 points adjacents que l'on injecte dans une formule.
            ;
            ; Le point courant est ensuite simplement dessiné à la position voulue.
            ;
            Case #PureBasic_Regular_Code
              For x = 1 To DrawingWidth - 1
                For y = 1 To DrawingHeight - 1
                  Value = ((Point(x + xTop, y + yTop - 1) + Point(x + xTop, y + yTop + 1) + Point(x + xTop + 1, y + yTop) + Point(x + xTop - 1, y + yTop)) / 4 + 1) % 64 + 192
                  Color = Value << 10 + Value
                  Plot(x + xTop, y + yTop, Color)
                Next
              Next
            ;
            ; In #PureBasic_Better_Code, we do no more use Point(x, y) but an 2 dimensions array to store points values.
            ;
            ; This array contains elements corresponding to screen pixels.
            ;
            ; Using this makes the listing easy to understand but the performances are much better
            ;=======================================================================================
            ; Dans la version #PureBasic_Better_Code on ne va plus utiliser la fonction Point(x, y) mais un tableau qui permet de mémoriser les
            ; valeurs des points.
            ;
            ; Ce tableau est à deux dimensions et chaque élément x, y du tableau représente fidèlement un point de l'écran
            ;
            ; Par contre le tracé du point courant est fait avec la fonction Plot, dont les performances restent assez bonnes.
            ;
            ; De là l'écriture est encore assez lisible ... et les performances très différentes
            ;
            Case #PureBasic_Better_Code
              For x = 1 To DrawingWidth - 1
                For y = 1 To DrawingHeight - 1
                  Value = ((DrawingArray(x, y - 1) + DrawingArray(x, y + 1) + DrawingArray(x - 1, y) + DrawingArray(x + 1, y)) / 4 + 1) & 63 + 192
                  Color = Value << 10 + Value
                  DrawingArray(x, y) = Color
                  Plot(x + xTop, y + yTop, Color)
                Next
              Next
            ;
            ; In #PureBasic_Optimized_Code a single dimension array is used.
            ;
            ; This makes the code a bit more difficult to understand but will make easier later optimization.
            ;=============================================================================
            ; Dans la version #PureBasic_Optimized_Code on utilise un tableau linéaire et non plus une matrice à deux dimensions.
            ;
            ; L'écriture du code est sensiblement plus lourde mais permettra d'aborder la phase d'optimisation suivante lus aisément.
            ;
            Case #PureBasic_Optimized_Code
              For x = 1 To DrawingWidth - 1
                For y = 1 To DrawingHeight - 1
                  xy = y * DrawingWidth + x
                  Value = ((DrawingArea(xy - DrawingWidth) + DrawingArea(xy + DrawingWidth) + DrawingArea(xy - 1) + DrawingArea(xy + 1)) / 4 + 1) & 63 + 192
                  Color = Value << 10 + Value
                  DrawingArea(xy) = Color
                  Plot(x + xTop, y + yTop, Color)
                Next
              Next
            ;
            ; #PureBasic_LowLevel_Code uses both the array and a direct calculation of pixels addresses to the drawing buffer.
            ;
            ; This calculation will not make performances better right now, but will help to master direct copy of array values to pixels
            ;====================================================================================
            ; Dans #PureBasic_LowLevel_Code, on va utiliser simultanément un tableau pour mémoriser les points et un calcul de l'adresse des
            ; points dans le buffer d'écran.
            ;
            ; Ce calcul n'apportera pas directement d'améliorations de performances, mais permettra de maîtriser la copie directe d'une valeur du tableau sur l'écran.
            ;
            Case #PureBasic_LowLevel_Code
              DrawingBuffer = DrawingBuffer()
              DrawingBufferPitch = DrawingBufferPitch()
              For x = 1 To DrawingWidth - 1
                X4 = DrawingBuffer + (x + xTop) << 2
                For y = 1 To DrawingHeight - 1
                  xy = y * DrawingWidth + x
                  Value = ((DrawingArea(xy - DrawingWidth) + DrawingArea(xy + DrawingWidth) + DrawingArea(xy - 1) + DrawingArea(xy + 1)) / 4 + 1) & 63 + 192
                  Color = Value << 10 + Value
                  DrawingArea(xy) = Color
                  Color = (Color & $FF0000) >> 16 + (Color & $00FF00) + (Color & $0000FF) << 16
                  Address = DrawingBufferPitch * (y + yTop) + X4
                  PokeL(Address, Color)
                Next
              Next
            ;
            ; Here we try to "chew" the former code in order to get only simple low level instructions.
            ;
            ; Only one operation per line and no more than two variables in a single line.
            ;
            ; Thanks to PureBasic coding convention we can write :
            ;
            ; a + 1 instead of a = a + 1
            ; a + b instead of a = a + b
            ;
            ; etc
            ;
            ; c = a + b will be replaced by
            ; c = a
            ; c + b
            ;
            ; The resulting code will not be optimized as good as the compiler does, but it will be fast and close to machine level.
            ;===========================================================================
            ; Le but du code développé ici est de se rapprocher le plus possible des instructions les plus élémentaires.
            ;
            ; On essaye de proscrire toute écriture qui consiste à cumuler plusieurs opérations sur une même ligne
            ;
            ; Pour y parvenir il suffit d'ajouter des variables temporaires lorsque c'est nécessaire.
            ;
            ; Dans ce style d'écriture on utilisera de préférence la notation unaire de PureBasic, c'est à dire par exemple :
            ;
            ; a + 1 au lieu de a = a + 1
            ; a + b au lieu de a = a + b
            ;
            ; etc
            ;
            ; On s'interdit également d'utiliser trois variables sur une même ligne :
            ;
            ; c = a + b sera donc déployé en 2 lignes
            ; c = a
            ; c + b
            ;
            ; Cette écriture donnera un code très rapide, même si il n'est pas tout à fait aussi rapide que le modèle #PureBasic_LowLevel_Code précédent
            ;
            ; Cette étape est une manière réaliste de passer de l'optimisation langage évolué à l'optimisation assembleur. La tentative de traduire
            ; directement le code #PureBasic_Optimized_Code est généralement vouée à de malheureuses déconvenues et n'apporte jamais de meilleurs résultats
            ; que le code généré par le compilateur.
            ;
            Case #PureBasic_Chewed_Code
              DrawingBuffer = DrawingBuffer()
              DrawingBufferPitch = DrawingBufferPitch()
              For x = 1 To DrawingWidth - 1
                X4 = x
                X4 + xTop
                X4 << 2
                X4 + DrawingBuffer
                For y = 1 To DrawingHeight - 1
                  xy = DrawingWidth
                  xy * y
                  xy + x
                  a = xy
                  a - DrawingWidth
                  Value = DrawingArea(a)
                  a = xy
                  a + DrawingWidth
                  Value + DrawingArea(a)
                  a = xy
                  a - 1
                  Value + DrawingArea(a)
                  a = xy
                  a + 1
                  Value + DrawingArea(a)
                  Value >> 2
                  Value + 1
                  Value & 63
                  Value + 192
                  Color = Value
                  Color << 10
                  Color + Value
                  DrawingArea(xy) = Color
                  Color1 = Color
                  Color1 & $FF0000
                  Color1 >> 16
                  Color2 = Color
                  Color2 & $00FF00
                  Color3 = Color
                  Color3 & $0000FF
                  Color3 << 16
                  Color = Color1
                  Color + Color2
                  Color + Color3
                  Address = y
                  Address + yTop
                  Address * DrawingBufferPitch
                  Address + X4
                  PokeL(Address, Color)
                Next
              Next
            ;
            ; Here we take the chewed code and translate it to ASM with some more optimization
            ;
            ; Especially we take care to avoid to store values in unnecessary variables.
            ;
            ; We can consider processor's registers as variables but with the limitation that any PureBasic instruction inserted between ASM lines
            ; may change registers values.
            ;
            ; So this is necessary to stay in ASM as far as possible to not loose registers values otherwise it is necessary to store registers all the time.
            ;=========================================================================================
            ; Le code #ASM_Code est la reprise du code #PureBasic_Chewed_Code avec quelques optimisations
            ;
            ; On s'attache en particulier à éliminer le report de valeurs de registres dans des variables temporaires.
            ;
            ; La limitation en nombre de registres oblige bien entendu à être très soigneux dans le choix des variables temporaires éliminées.
            ;
            ; On peut considérer pratiquement que les registres sont des variables, mais en conservant à l'esprit que l'exécution
            ; de toute instruction langage évolué remet en question l'état de tous les registres CPU.
            ;
            ; Il faut par conséquent rester en assembleur le plus longtemps possible pour éviter de risquer de perdre la valeur d'un registre en cours de route,
            ; ou inversement d'être contraint de sauvegarder tel ou tel registre dans une variable mémoire ce qui diminuerait la qualité d'optimisation.
            ;
            Case #ASM_Code
              DrawingBuffer = DrawingBuffer()
              DrawingBufferPitch = DrawingBufferPitch()
              X4.l
              xy.l
              For x = 1 To DrawingWidth - 1
                !  MOV     eax, dword[v_x]                                     ; eax = x
                !  ADD     eax, dword[v_xTop]                               ; eax + xTop
                !  SAL      eax, 2                                                    ; eax << 2
                !  ADD     eax, dword[v_DrawingBuffer]                  ; eax + DrawingBuffer
                !  MOV     dword[v_X4], eax                                   ; X4 = eax
                For y = 1 To DrawingHeight - 1
                  !  MOV     eax, dword[v_DrawingWidth]                           ; eax = DrawingWidth
                  !  IMUL    eax, dword[v_y]                                    ; eax * y
                  !  ADD     eax, dword[v_x]                                   ; eax + x

                  !  MOV     ebp, dword[a_DrawingArea]                   ; ebp = @DrawingArea()
                  !  MOV     ecx, eax                                               ; ecx = eax
                  !  SUB      ecx, dword[v_DrawingWidth]                           ; ecx - DrawingWidth
                  !  SAL      ecx, 2                                                   ; ecx * 4
                  !  MOV     edi, dword[ebp+ecx]                              ; edi = PeekL(ebp + ecx)

                  !  MOV     ecx, eax                                                ; ecx = eax
                  !  ADD     ecx, dword[v_DrawingWidth]                            ; ecx + DrawingWidth
                  !  SAL      ecx, 2                                                   ; ecx * 4
                  !  ADD     edi, dword[ebp+ecx]                              ; edi + PeekL(ebp + ecx)

                  !  MOV     ecx, eax                                                ; ecx = eax
                  !  DEC     ecx                                                        ; ecx - 1
                  !  SAL      ecx, 2                                                    ; ecx * 4
                  !  ADD     edi, dword[ebp+ecx]                               ; edi + PeekL(ebp+ecx)

                  !  ADD     ecx, 8                                                    ; ecx + 8 (soit ecx = ((eax - 1) + 2) * 4
                  !  ADD     edi, dword[ebp+ecx]                               ; edi + PeekL(ebp + ecx)
                  
                  !  SAR     edi, 2                                                     ; edi >> 2
                  !  INC      edi                                                        ; edi + 1
                  !  And     edi, 63                                                   ; edi & 63
                  !  ADD     edi, 192                                                  ; edi + 192

                  !  MOV     edx, edi                                                 ; edx = edi
                  !  MOV     ebx, edx                                                ; ebx = edx
                  !  SAL      edx, 10                                                  ; eax = edx << 10
                  !  ADD     edx, ebx                                                ; edx = ebx

                  !  MOV      ecx, eax                                                ; ecx = eax
                  !  SAL       ecx, 2                                                   ; ecx * 4
                  !  MOV      [ebp+ecx], edx                                      ; PokeL(ebp+ecx, edx)

                  !  MOV      ecx, dword[v_y]                                  ; ecx = y
                  !  ADD      ecx, dword[v_yTop]                            ; ecx + yTop
                  !  IMUL     ecx, dword[v_DrawingBufferPitch]         ; ecx * DrawingBufferPitch
                  !  ADD      ecx, dword[v_X4]                                ; ecx + X4
                  !  BSWAP  edx                                                     ; edx (00RRGGBB) => (BBGGRR00)
                  !  SAR       edx, 8                                                 ; edx(BBGGRR00) => (00BBGGRR)
                  !  MOV      [ecx], edx                                           ; PokeL(ecx, edx)
                Next
              Next
            ;
            ; In #PureBasic_LowLevel_Code2 the same idea is used than in former #PureBasic_LowLevel_Code but addressing is linearized 
            ; Buffer addressing is no more x, y based but only a single variable is used.
            ;
            ; The address of the horizontal neighbor of a given point is the address of this point -/+ 1.
            ; The address of the vertical neighbor of a given point is the address of this point -/+ DrawingWidth.
            ;
            ; Using this method the point to draw is accessed the fastest.
            ;
            ; Meantime pixels values are stored in the array which is addressed using two variables to calculate unary index
            ; of the array easily, allowing to avoid the double address calculation.
            ;
            ; Obviously this does not look far from former code, it renders completely different results.
            ;
            ; In order to access to the best possible ASM optimization later, For / Next loops are replaced by Repeat / Until.
            ;
            ; Pixel value calculation is unchanged.
            ;=====================================================================
            ; Dans la version #PureBasic_LowLevel_Code2 on reprend le même principe mais on a linéarisé l'adressage
            ; Ici le buffer de l'écran est adressé avec une seule variable d'adresse qui est incrémentée de 4 octets pour passer
            ; point suivant et d'une ligne moins la DrawingWidth de tracé pour passer à la ligne suivante.
            ;
            ; Cette méthode permet d'adresser le pixel à tracer au plus vite.
            ;
            ; Dans le même temps les valeurs des points sont toujours stockées dans un tableau qui lui est adressé
            ; à partir de deux variables x et y en recalculant l'indice unaire du tableau pour éviter le double calcul d'adresse.
            ;
            ; La méthode paraît peu différente à priori, mais les résultats n'ont rien à voir.
            ;
            ; Pour amener à une meilleure optimisation ultérieure en assembleur, les boucles For / Next ont été remplacées par des Repeat / Until
            ;
            ; Le calcul de valeur d'un pixel reste inchangé.
            ;
            Case #PureBasic_LowLevel_Code2
              DrawingBuffer = DrawingBuffer()
              DrawingBufferPitch = DrawingBufferPitch()
              BufferAddress = DrawingBuffer + 4 * (xTop + 1) + yTop * DrawingBufferPitch
              ArrayAddress = DrawingWidth + 1
              y = 1
              Repeat
                x = 1
                Repeat
                  Value = ((DrawingArea(ArrayAddress - DrawingWidth) + DrawingArea(ArrayAddress + DrawingWidth) + DrawingArea(ArrayAddress - 1) + DrawingArea(ArrayAddress + 1)) / 4 + 1) & 63 + 192
                  Color = Value << 10 + Value
                  DrawingArea(ArrayAddress) = Color
                  Color = (Color & $FF0000) >> 16 + (Color & $00FF00) + (Color & $0000FF) << 16
                  PokeL(BufferAddress, Color)
                  BufferAddress + 4
                  ArrayAddress + 1
                  x + 1
                Until  x > DrawingWidth - 1
                ArrayAddress + 1
                BufferAddress + DrawingBufferPitch - 4 * (DrawingWidth - 1)
                y + 1
              Until y > DrawingHeight - 1
            ;
            ; Here is the optimized ASM listing of the #PureBasic_LowLevel_Code2
            ;======================================================
            ; Voici une version assembleur optimisée pour le code #PureBasic_LowLevel_Code2
            ;
            Case #ASM_LowLevel_Code2
              DrawingBuffer = DrawingBuffer()
              DrawingBufferPitch = DrawingBufferPitch()
              !  MOV    ebx, dword[v_DrawingBuffer]                      ; ebx = DrawingBuffer
              !  MOV    edi, dword[v_xTop]                                     ; edi = xTop
              !  INC     edi                                                             ; edi + 1
              !  SAL     edi, 2                                                         ; edi * 4
              !  ADD    ebx, edi                                                      ; ebx + edi
              !  MOV    edi, dword[v_yTop]                                     ; edi = yTop
              !  IMUL   edi, dword[v_DrawingBufferPitch]                 ; edi * DrawingBufferPitch
              !  ADD    ebx, edi                                                     ; ebx + edi
              !  MOV    dword[v_BufferAddress], ebx                       ; BufferAddress = ebx
              !  MOV    ebx, dword[v_DrawingWidth]                       ; ebx = DrawingWidth
              !  INC     ebx                                                            ; ebx + 1
              !  MOV    dword[v_ArrayAddress], ebx                        ; ArrayAddress = ebx
              !  MOV    dword[v_y], 1                                             ; y = 1
              !_RepeatBN21:                                                         ; Repeat / Until return label
                !  MOV    dword[v_x], 1                                           ; x = 1
                !_RepeatBN22:                                                       ; Repeat / Until return label
                  !  MOV      ebp, dword[a_DrawingArea]                     ; ebp = DrawingArea
                  !  MOV      ecx, dword[v_ArrayAddress]                    ; ecx = @ArrayAddress
                  !  MOV      eax, ecx                                                 ; eax = ecx
                  !  SUB      eax, dword[v_DrawingWidth]                    ; eax - DrawingWidth
                  !  SAL       eax, 2                                                    ; eax * 4
                  !  MOV      edi, dword[ebp+eax]                               ; edi = PeekL(ebp+eax]

                  !  MOV      eax, ecx                                                 ; eax = ecx
                  !  ADD      eax, dword[v_DrawingWidth]                    ; eax - DrawingWidth
                  !  SAL       eax, 2                                                    ; eax * 4
                  !  ADD      edi, dword[ebp+eax]                               ; edi = PeekL(ebp+eax]

                  !  MOV      eax, ecx                                                 ; eax = ecx
                  !  DEC      eax                                                        ; eax - 1
                  !  SAL       eax, 2                                                    ; eax * 4
                  !  ADD      edi, dword[ebp+eax]                               ; edi = PeekL(ebp+eax]

                  !  ADD      eax, 8                                                    ; eax + 8
                  !  ADD      edi, dword[ebp+eax]                               ; edi = PeekL(ebp+eax]

                  !  SAR      edi, 2                                                      ; edi / 4
                  !  INC       edi                                                         ; edi + 1
                  !  And      edi, 63                                                    ; edi & 63
                  !  ADD      edi, 192                                                  ; edi + 192
                  !  MOV      ebx, edi                                                  ; ebx = edi

                  !  SAL       ebx, 10                                                   ; ebx << 10
                  !  ADD      ebx, edi                                                  ; ebx + edi

                  !  MOV      eax, ecx                                                  ; eax = ecx
                  !  SAL       eax, 2                                                     ; eax * 4
                  !  MOV      dword[ebp+eax], ebx                               ; PokeL(ebp+eax, ebx)

                  !  BSWAP  ebx                                                         ; ebx (00RRGGBB) => (BBGGRR00)
                  !  SAR       ebx, 8                                                     ; ebx(BBGGRR00) => (00BBGGRR)

                  !  MOV      eax,dword[v_BufferAddress]                     ; eax = @BufferAddress
                  !  MOV      [eax], ebx                                               ; PokeL(eax, ebx)

                  !  ADD      dword[v_BufferAddress], 4                        ; BufferAddress + 4
                  !  INC       dword[v_ArrayAddress]                             ; ArrayAddress + 1
                  !  INC       dword[v_x]                                               ; x + 1
                  !  MOV      ebx, dword[v_x]                                        ; ebx = x
                  !  MOV      edi, dword[v_DrawingWidth]                       ; edi = DrawingWidth
                  !  DEC      edi                                                           ; edi - 1
                  !  CMP      ebx, edi                                                    ; if ebx <= edi
                  !  JLE        _RepeatBN22                                            ; Goto RepeatBN22
              
              !  INC     dword[v_ArrayAddress]                                   ; ArrayAddress + 1
              !  MOV    ebx, dword[v_DrawingWidth]                           ; ebx = DrawingWidth
              !  DEC    ebx                                                                ; ebx - 1
              !  SAL     ebx, 2                                                            ; ebx / 4
              !  NEG    ebx                                                                 ; -ebx
              !  ADD    ebx, dword[v_DrawingBufferPitch]                    ; ebx + DrawingBufferPitch
              !  ADD    dword[v_BufferAddress], ebx                           ; BufferAddress + ebx
              !  INC     dword[v_y]                                                     ; y + 1
              !  MOV    edi, dword[v_DrawingHeight]                            ; edi = DrawingHeight
              !  ADD    edi, -1                                                            ; edi - 1
              !  MOV    ebx, dword[v_y]                                              ; ebx = y
              !  CMP    ebx, edi                                                          ; if ebx <= edi
              !  JLE      _RepeatBN21                                                  ; Goto RepeatBN21
          EndSelect

          ;
          ; Keyboard events part
          ;============================
          ; Section de gestion des évènements clavier
          ;
          ExamineKeyboard()
          ; Change the code part to execute
          ; Modifie la section de code à exécuter
          If KeyboardPushed(#PB_Key_Left)
              ResetAll()
              ExecuteCode - 1
              If ExecuteCode < 0
                  ExecuteCode = 0
              EndIf
              Repeat
                ExamineKeyboard()
              Until KeyboardReleased(#PB_Key_Left)
          EndIf
          If KeyboardPushed(#PB_Key_Right)
              ResetAll()
              ExecuteCode + 1
              If ExecuteCode > #LastCode
                  ExecuteCode = #LastCode
              EndIf
              Repeat
                ExamineKeyboard()
              Until KeyboardReleased(#PB_Key_Right)
          EndIf
          ; Set / Unset the buffers synchronization
          ; Valide / invalide la synchronisation des buffers
          If KeyboardPushed(#PB_Key_Up)
              ResetAll()
              FlipBuffers = 1 - FlipBuffers
              Repeat
                ExamineKeyboard()
              Until KeyboardReleased(#PB_Key_Up)
          EndIf
          If KeyboardPushed(#PB_Key_Down)
              ResetAll()
              FlipBuffers = 1 - FlipBuffers
              Repeat
                ExamineKeyboard()
              Until KeyboardReleased(#PB_Key_Down)
          EndIf
          ; Change the drawing area size
          ; Modifie la taille de la zone de dessin
          If KeyboardPushed(#PB_Key_Pad4)
              ResetAll()
              WidthHeight - 1
              If WidthHeight < 0
                  WidthHeight = 0
              EndIf
              Repeat
                ExamineKeyboard()
              Until KeyboardReleased(#PB_Key_Pad4)
              DrawingWidth = DrawingWidth(WidthHeight)
              DrawingHeight = DrawingHeight(WidthHeight)
              xTop = (ScreenXSize - DrawingWidth) / 2 + 1
              yTop = (ScreenYSize - DrawingHeight) / 2 + 1
              xBottom = xTop + DrawingWidth - 2
              yBottom = yTop + DrawingHeight - 2
          EndIf
          If KeyboardPushed(#PB_Key_Pad6)
              ResetAll()
              WidthHeight + 1
              If WidthHeight > LastSize
                  WidthHeight = LastSize
              EndIf
              Repeat
                ExamineKeyboard()
              Until KeyboardReleased(#PB_Key_Pad6)
              DrawingWidth = DrawingWidth(WidthHeight)
              DrawingHeight = DrawingHeight(WidthHeight)
              xTop = (ScreenXSize - DrawingWidth) / 2 + 1
              yTop = (ScreenYSize - DrawingHeight) / 2 + 1
              xBottom = xTop + DrawingWidth - 2
              yBottom = yTop + DrawingHeight - 2
          EndIf
          ; Control the elapsed time since the last integer second
          ; Contrôle le temps écoulé depuis la dernière seconde entière
          If ElapsedMilliseconds() - tz => 1000
              tz = ElapsedMilliseconds()
              FPS = NFrames
              TFrames + FPS
              NFrames = 0
              AFrames + 1
          EndIf
          NFrames + 1
          ; Display statistics and parameters
          ; Affiche les statistiques et les paramètres
          BackColor(0, 0, 0)
          FrontColor(255, 255, 255)
          Locate(10, 40)
          DrawText("FPS " + Str(FPS) + "      Average : " + StrF(TFrames / AFrames, 2))
          Locate(10, 60)
          DrawText(CodeType(ExecuteCode) + "            ")
          Locate(10, 80)
          DrawText("FlipBuffers(" + Str(FlipBuffers) + ")")
          Locate(10, 100)
          DrawText(Str(DrawingWidth) + "x" + Str(DrawingHeight))
        StopDrawing()
      Until KeyboardReleased(#pb_key_escape)
  EndIf 
End

DataSection
  Data.s "#PureBasic_Regular_Code", "#PureBasic_Better_Code", "#PureBasic_Optimized_Code", "#PureBasic_LowLevel_Code"
  Data.s "#PureBasic_Chewed_Code", "#ASM_Code", "#PureBasic_LowLevel_Code2", "#ASM_LowLevel_Code2"
  Data.l 128, 128
  Data.l 256, 256
  Data.l 320, 240
  Data.l 480, 360
  Data.l 640, 480
  Data.l 800, 600
EndDataSection

Mon avatar reproduit l'image de 4x1.8m présentée au 'Salon international du meuble de Paris' en janvier 2004, dans l'exposition 'Shades' réunisant 22 créateurs autour de Matt Sindall. L'original est un stratifié en 150 dpi.
filperj
Messages : 395
Inscription : jeu. 22/janv./2004 1:13

Message par filperj »

Je n'arrive même pas à repérer l'algo de martin dans tout ça :oops:
Je me demandai si tu avais trouvé une astuce pour éviter de lire 4 fois chaque octet, ou autre optimisation?
Le chaos l'emporte toujours sur l'ordre
parcequ'il est mieux organisé.
(Ly Tin Wheedle)
filperj
Messages : 395
Inscription : jeu. 22/janv./2004 1:13

Message par filperj »

Ah, j'ai trouvé: tu utilises des longs pour des variables à 6 bits significatifs, tricheur :twisted:
Le chaos l'emporte toujours sur l'ordre
parcequ'il est mieux organisé.
(Ly Tin Wheedle)
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

chez moi le code de Fweil va trop vite !!
ça pert de son charme je ne suis plus "envouté par l'effet !!"
y a plus l'effet hipnotique !!

je prefere la version de filperj !! :D
(c'est mon avis !!)
Répondre