GT Turbo :
[...]Le sprite dessiné en temps réel d'accord mais il y a du code généré ou une astuce du style car c'est impossible sur un ST, je penses que Frost sera d'accord avec moi, car faire une extraction de bits, zooming et réecriture en ram, ca fait vite grimper la facture.[...]
Oui et non, j'avais fait une petite démo d'un concept en ASM sur mon Falcon, mais j'arrives plus à foutre la main dessus :/ Bon n'empèche je me souvient de la technique que j'avais employée...
Prenons le cas du mode ST 16 couleurs (4 bits/pixels, 2 pixels/byte). On part d'un sprite 16x16 (plus facile pour comprendre par la suite), et on commence quelques sprites précalculés. Mais ATTENTION, c'est direct là que ça commence à être rigolo :
On précalcul tous les sprites en multipliant simplement la largeur, *PAS* la hauteur, donc on obtien des sprites en 32x16, 48x16, 64x16, ... A toi de déterminer jusqu'à où tu veux aller. Ensuite tu fais une copie de chaque sprite que tu décale d'un pixel (avec le masque associé) -> 16x16 dans un 18x16 (un 20x16 en fait, à cause de l'alignement pour avoir une ligne sur 10 octets plutôt que 9), 32x16 dans un 34x16 (36x16 en fait, ligne de 18 octets), 64x16 dans un 66x16 (68x16 en fait), ...
Un fois que tu as ta collection de sprites, la routine de zoom est relativement simple, une double boucle X/Y, l'entrelacement de 4 sprites par ligne. J'explique :
On va commencer par ne s'occuper que de générer une ligne, les suivantes seront calquées sur la première. En fait plutôt que de faire une copie dès le départ, on va générer une liste d'offsets pour générer une ligne de sprite zoomé à partir de 4. On va travailler en virgule fixe avec une précision de (tiens ne je sais plus ducoup, j'avais calculé ça à l'époque) 4 bits il me semble. La boucle X sera elle même découpée en deux boucles à base de ADDX.
Bon imaginons que tu veux faire un zoom de 1.56 fois de ton sprite, tu sélectionnes les sprites 1x et 2x (ainsi que leurs version décalées). 1.56 en précision 4 bits, c'est 24.96 (donc 24). Il s'agit d'une faire une boucle qui va compter de 0 à 24 en tapant soit dans la version 1x, soit dans la version 2x et leurs versions décalées (je n'ai plus le détail en tête, mais je me rappelle que je faisait ça à coup de ADDX, le bit de retenu servant à choisir la version décalée ou pas, ou la version 1x ou 2x, je ne sais plus, ça date). Bref tu te compose une petite liste d'offset avec des WORD qui ont le format suivant :
bits
15 : Sprite 1x ou 2x
14 : Sprite décalé ou pas
13 à 0 : Offset du pixel dans la ligne (soit une ligne de 16 KiB max, 32768 pixels)
Une fois que tu as fini ça, tu passes à la copie proprement dites de la ligne. Tu gardes les 4 pointeurs sources dans A0-A3, et la destination dans A4. Il ne te restes plus qu'à lire ta liste d'offset, et en fonction des bits 15 et 14, choisir ta source. Il sagit de lire octet par octet (2 pixels à chaque fois, d'où l'intéret du prédécalage), aussi récupère directement WORD à WORD dans les registres D0-D3, et fait un simple ROR 8 si tu doit lire à une adresse impaire (bit 0 à 1).
Pour la boucle en Y, c'est super simple, c'est le même principe avec une virgule fixe de 0 à 24, mais là tu changes de ligne seulement sur la retenue (donc des fois tu refait exactement la même ligne, des fois tu passes à la suivante). Il te suffit pour ça de mettre ou non tes registres sources A0-A3 en les faisants pointer sur la ligne suivante dans tes sprites, puis de réappliquer ta liste d'offsets que tu avais calculé pour la première ligne. L'optimisation ultime consisterait à ne simplement que recopier la ligne que tu viens d'écrire tant que tu n'as pas à changer de ligne source dans tes sprites, par contre ça risque de compliquer les masques aux bordures de ton sprite. Donc le plus simple est de réappliquer simplement la routine de copie par offset.
J'avais aussi intégré une valeur de rotation/déformation par shearing, mais alors chaque commande d'offset prenait 32 bits et nécessitait un autre jeu de tables de précalcul pour la sélection de la ligne (0 à 15). Mais le résultat était très moche (les sprites zoomés et rotationés ne ressemblaient pas à une grosse mosaique avec des carrés tournés, mais plutôt à un nuage de point).
Enfin voilà ce dont je me rappelle, j'avais quand même passé 3 semaines à peaufiner l'algo pendant mes études à l'IUT (le soir, plutôt que de faire mes devoirs). Mais bon, je faisait d'autres trucs à coté, et il devrait être possible de réimplémenter l'algo plus rapidement... En faisait gaffe de pas dépasser d'une ligne sur l'autre et en bas de l'écran. Pour ça il aurait fallu simplement modifier les valeurs de la boucle X/Y en clippant les valeurs par rapport à la proximité des bordures de l'écran :
Si dépasse en haut : compteur Y de 0 à 24 -> 5 à 24 par exemple (commence la copie plus bas, mettre à jour directement les registres source A0-A3)
Si dépasse en bas : compteur Y de 0 à 24 -> 0 à 13 par exemple (ne termine pas la copie)
Si dépasse à gauche : compteur X de 0 à 24 -> 8 à 24 par exemple (un peu compliqué, commence la copie de la ligne plus tard, il faut générer la liste d'offset en conséquence)
Si dépasse à droite : compteur X de 0 à 24 -> 0 à 18 par exemple (ne termine pas la copie de la ligne, générer une ligne d'offset plus courte)
Voilà voilà

Et ça n'a ni besoin de code généré ou automodifié, ça passe aussi sur Falcon030 (puisque développé dessus à l'origine) et que je bougeait le sprite avec la souris en temps réel, et zoomait en temps réel avec le bouton gauche enfoncé (et en bougeant la souris de haut en bas). Pour la rotation, j'avais utilisé le bouton droit et un mouvement gauche-droite...
Kochise