PDA

Voir la version complète : [Dev] Cherche Astuces


Mollusk
05/02/2006, 21h38
Salut !

On m'a posé une question sur un autre forum, et je dois admettre que je ne m'y connais pas trop...
En fait, j'aurai voulu 'lister' les différentes astuces de programmation possible quand on fait un jeu, histoire de se simplfiier la vie ou d'accélerer un peu les choses. Je veux des choses en C, donc tous les fanas d'ASM, ca ira, merci :)

En gros, ca serait des trucs du genre :
- Nombres a virugle fixe
- Utiliser & au lieu de % quand possible
- Utiliser les décallage de bits au lieu des multiplications/divisions
- Tableau de pointeurs sur fonction
- Talbeau de divisions
- Organistion intelligente des if/else

etc...

Merci d'avance !

Dr.Vince
05/02/2006, 22h56
bah t'as qu'a filer l'adresse de PA au mec qui t'as posé la question :D

Mollusk
05/02/2006, 22h58
non mais j'aimerai regrouper un peu les thèmes... pas forcément toutes les infos, mais au moins les noms

Japi
06/02/2006, 01h07
Franchement, la programmation en elle même c'st de l'astuce. ^^

Chaque situation peut etre codé de 3millions de façon différente et ya pas une bonne une mauvaise, juste certaines qui vont plus vite, d'autres plus généraliste, d'autres plus lisible.
Pour aller plus vite, faut dejà connaitre sa vitesse, les points du programme qui sont lents, donc savoir benchmarker correctement.

Parce que une mauvaise otpimisation peut etre moins performante qu'un bon code de base. Par exmple de faire un decalage de bit alors qu'on est pas dans une zone critique, ça sert strictement à rien, en plus, le compilo optimise dejà bien si il est bon.
Ca sert à rien de parcourir son code et des qu'on voit une multiplication, sauter dessus pour la convertir en décalage. Faut le faire là où y en a besoin.

Le principal truc, c'est d'avoir un bon compilo. apres les gens vous disent, ouais, les float, ça ralenti, mais si t'en as besoin, ben t'en as besoin et puis c'est tout.

Mon seul conseil sur GBA, c'est d'utiliser au max les fonctions hard qui sont les plus rapide et qui ne pourront jamais etre égalées question vitesse. Si elles sont là, c'est pour aider, alors autant s'en servir à fond.

Dr.Vince
06/02/2006, 01h45
non mais j'aimerai regrouper un peu les thèmes... pas forcément toutes les infos, mais au moins les noms

y avait un topic sympa sur l'ancien PA, qui recensait tous les liens vers les différents aspect et problèmes rencontrés lors du dev d'un jeu.

Faudrait en faire un sur le nouveau PA ce serait cool !!!

[EDIT] voilà le lien : http://www.playeradvance.org/old/index.php?showtopic=12355

Mollusk
06/02/2006, 09h32
Hmm, j'ai pas tellement trouvé ce que je cherche dans ce topic en fin de compte. A part celui sur les trajectoires et nombres à virugles fixes (excellent :p), le reste c'est des trucs vers les libs, des sprites, de sons, etc...

Si au lieu d'avoir un mega-gros switch/case, je fais des fonctions avec pointeurs sur fonction, on y gagne ?

omg
06/02/2006, 10h01
pour les décalages de bits je crois que c'est du style :
B = B >> 1;
ce qui décale tous les bits vers la droite le plus petit bit étant perdu
ce qui fait en gros une division par deux de B
et
B = B << 1;
ce qui décale tous les bits de B d'un cran vers la gauche le plus grand bit étant perdu
ce qui fait en gros une multiplication par deux de B

C'est une operation plus rapide que la multiplication ou la division qu'il me semble j'utilisais sur les 68hc11...

ceci n'est qu'une suposition, des restes de mes cours de C que j'ai eu il y a plusieurs années...

Mollusk
06/02/2006, 10h05
omg, tout a fait oui :)

Nesgba
06/02/2006, 10h32
il faut tout faire pour eviter les float quitte a rettaper tout ton algo, c'est impressionant les pertes que tu as en les utilisants, vive les fixed point.

moi j'ai une question:
il est plus rapide d'acceder a une structure directement ou en utilisant un pointeur ? avec gcc bien sur :whst:

par exemple perso pour les fixed points j'utilise un truc de ce genre la:

#define IRIS_SpriteFixedPointX(n) IRIS_Sprites[n].DepX = (IRIS_Sprites[n].MoveX<<7)>>7 ;\
IRIS_Sprites[n].MoveX_fixed += IRIS_Sprites[n].DepX ;\
IRIS_Sprites[n].CoorX = IRIS_Sprites[n].MoveX_fixed>>7 ;

Brunni
06/02/2006, 10h52
Mollusk> Bien sûr que c'est plus rapide les tableaux de fonctions, à fond même. D'ailleurs t'as déjà vu un émulateur codé avec un switch/case pour chaque opcode? :p
Et même, en remplaçant ton switch par des if / else if tu gagnes parfois énormément, mais ce n'est pas valable pour toutes les plate-formes. Il me semble que c'est le cas sur GBA, mais c'est à vérifier.
Comme je l'avais déjà dit sur l'ancien forum, pour gérer mes objets (sprites), j'utilise des pointeurs vers des fonctions. En fait, chaque sprite contient dans sa structure des infos du genre sa position, sa vitesse, et une zone (p.ex. 256 bits) utilisable pour ce qu'on veut, dépendant du type de sprite, ainsi qu'un pointeur vers une fonction. A chaque frame, la liste est parcourue et pour chaque objet sa fonction est appelée avec ledit objet en paramètre. Chaque fonction prend toujours les mêmes arguments, c'est-à-dire: le perso principal, l'objet lui-même et une variable donnant des infos (le sprite est hors écran, il va être détruit, etc.). Dans cette fonction, on s'occupe donc d'afficher le sprite, le déplacer, et gérer les collisions avec le personnage passé en paramètre. Exemple:
typedef struct {
int x, y;
u8 donnees[32];
void (*fonction)(PERSO*,OBJET*,u32);
} OBJET;

//Informations sur le rocher (ce qu'on fait des "donnees" de l'objet)
typedef struct {
u16 timer;
} INFOS_ROCHER;

//Gestionnaire du rocher
void hoRocher(PERSO *p, OBJET *o, u32 infos) {
//Truc intéressant, on peut utiliser les données de l'objet pour ce qu'on veut, du moment qu'on ne dépasse pas les 32 octets alloués
INFOS_ROCHER *i = (void*)o->donnees;
//Le rocher se déplace d'un pixel sur la droite à chaque frame
o->x++;
//L'objet est détruit après 250 frames de lourde existence
i->timer ++;
if (i->timer > 250) {
DetruitObjet(o);
return;
}
//On dessine le sprite à chaque frame
DessineSprite(o->x, o->y, rocher_tiles, rocher_palette, TAILLE_32x32);
}

void main() {
OBJET monObjet; //Un objet (exemple un rocher)
PERSO sam; //Perso principal

//Initialise l'objet
monObjet.x = monObjet.y = 0;
monObjet.fonction = hoRocher;

[...]

//Gestion de l'objet
monObjet.fonction(&sam, &monObjet, 0);
}
Bon dans ce code les positions de l'objet sont gérées en entier, le mieux serait peut-être d'utiliser une virgule fixe, car pour faire un mouvement inférieur à 1 pixel par frame, ça devient un peu du bidouillage, mais tout dépend de ce que vous avez besoin. Une façon simple de manipuler les virgule fixe / entiers c'est de déclarer ses positions comme ça:
typedef struct {
static union {
struct {
u16 virguleX;
s16 intX;
};
s32 x;
};
} PERSO;
(A tester sur GBA, ça marche sur PC, mais il faudra peut-être enlever le static et inverser l'ordre de virguleX et intX).
Après on peut accéder à la partie entière en utilisant perso.intX, ce qu'il y a derrière la virgule avec perso.virguleX et le tout avec perso.x. Le défaut de cette méthode est que intX est obligatoirement 16 bits, ce qui pourrait être un peu limite pour certaines maps (si elle est plus grande que 2048x2048 blocs de 16x16 par exemple, ou 4096x4096 si vous remplacez les s16/s32 par u16/u32). Pour pallier à ça, on peut faire:
typedef struct {
static union {
struct {
u32 virguleX:8;
s32 intX:24;
};
s32 x;
};
};
Là on a 24 bits pour la partie entière et 8 pour la virgule, malheureusement c'est beaucoup plus lent, alors ne l'utilisez que si vous n'avez pas le choix!
Pour les calculs, les entiers 32 bits donnent en général des résultats plus rapides, mais tout dépend où ils sont. Si vos variables locales sont en IWRAM, comme avec HAM par défaut, alors tentez d'utiliser des valeurs 32 bits aux endroits critiques, particulièrement en ce qui concerne les index de tableau.
Voilà, optimisez bien votre code :) (comment ça "Nes sors de ce corps!"? :lol:)

Dr.Vince
06/02/2006, 12h15
t'es sûr de ton coup pour les switch Brunni ?? je pensais que c'était plus rapide que les if
ce serait bien d'avoir l'avis d'un pro de l'asm à ce sujet

Mollusk
06/02/2006, 13h19
D'ailleurs t'as déjà vu un émulateur codé avec un switch/case pour chaque opcode? Oui, donc je tairais le nom :p (mais il est sur ce forum)
Perso, j'utilise jamais de switch/case, je sais pas pourquoi mais j'ai jamais pu m'y faire.
Par contre, je ne vois pas trop pourquoi le if/elseif serait plus rapide, sinon où est l'intéret du switch/case ??? (dans mon humble esprit c'était une structure plus rapide/optimisée que le if/else pour les 'listes')

Sinon, Nes, c'est ce que je fais pour gérer mes coordonnées :)

J'ai oublié dans ma liste un détail important : les tables inversées pour remplacer les petites divisions quand possible (genre en mode7 tu dois gagner pas mal je suppose !)

Nesgba
06/02/2006, 13h31
pour les switch et les if ca depend de ce que tu veut faire
par exemple si tu as 10 case a mettre et si tu as une condition parmis ces 10 qui est succeptible de tomber genre 1 fois sur 2 vaut mieu que tu mette un if else mais si tu tombe sur la derniere condition tu te frappe 9 if else d'affilé et la vitesse de ton prog en prend un coup dans la tronche. :( faudrai faire des test avec gcc et voir le code asm qu'il en resulte.

brunni pourquoi tu ne met pas tout les paramettres de ton sprite dans la meme structure ? c'est plus simple a gerer.

[edit] a propos vous avez deja comparé un goto a un while ou un for ?

Japi
06/02/2006, 14h44
franchement, pour tout ça depend trop du compilo.

Pour les multiplications par exmple, si jamais le compilo convertit certaines des multiplication en "mul r0,r0,#unnombre" par exemple, ça va plus vite que de faire les décalages (parce que souvent y en a pas qu'un à faire). Ca depend donc des nombres à multiplier et tout.
Le for est convertit en goto par certains compilo avec decrementation d'un compteur, donc pareil, il optimise pour vous ... etc

Mollusk
06/02/2006, 15h10
En général je m'amuse pas à faire 40 décalages comme nes, je fais juste un décalage quand c'est possible... Voire meme parfois je m'arrange pour avoir un nombre d'entités permettant de faire des décalages et des & plutot que des multiplications/divisions et des % (genre je devais prendre plusieurs points parmis un grand nombre pour la reco de forme, alors j'ai tablé sur 16 histoire de faire les décalages plutot que des divisions)

Nesgba
06/02/2006, 15h46
hum... si je me souvien bien une multiplication prend quelques dixaines de cycles a etre executée et une division beaucoup + que ca alors qu'un decalage en prend ... 1.
donc pour moi c'est tout vu. je prefere me taper 6 decalages d'affilé que me trainer une multiplication. :whst:

Mollusk
06/02/2006, 15h57
et sinon, puisque j'ai réussi à chopper des dev sur un topic, j'avais une petite question. Il semble que j'ai un soucis avec le linkage de fichier .bin, quelqu'un m'a dit que par défaut ils n'étaient pas placés à 32bit pret, qu'en est-il ? (désolé, je m'exprime mal :s)

Brunni
06/02/2006, 16h49
pour les switch et les if ca depend de ce que tu veut faire

par exemple si tu as 10 case a mettre et si tu as une condition parmis ces 10 qui est succeptible de tomber genre 1 fois sur 2 vaut mieu que tu mette un if else mais si tu tombe sur la derniere condition tu te frappe 9 if else d'affilé et la vitesse de ton prog en prend un coup dans la tronche. faudrai faire des test avec gcc et voir le code asm qu'il en resulte.
Ben oué, 9 conditions fausses, ça fait quand même... 18 cycles :w00t: (je te taquine hein nes ;)).
brunni pourquoi tu ne met pas tout les paramettres de ton sprite dans la meme structure ? c'est plus simple a gerer.
Parce que c'est une structure générale pour tous les objets qui existent. Et tous les objets n'ont pas les mêmes propriétés, mais certaines (comme les positions) sont communes. C'est pourquoi il y a cet espace mémoire avec lequel tu fais ce que tu veux selon ton objet. Par exemple, si c'est un boss, tu peux l'utiliser pour stocker son énergie, sa couleur ou sa trajectoire, tandis que si c'est une pièce, tu n'auras qu'à stocker le nécessaire pour l'animer lorsque ton perso la prendra (pas besoin de l'énergie ou la trajectoire). Si tu fais une structure qui correspond à tous tes types d'ennemis, tu te retrouveras forcément avec des variables en doublons, ou alors tu devras en faire des milliers de différentes.

thoduv
06/02/2006, 16h51
Sympa comme topic, y'a des choses intéréssantes qui ressortent !

J'ai pas tout saisi le coup des "fixed points" mais ca m'interesse parce jusqu'à maintenant, dans ces cas là je procédais à peu près comme ca :


typedef struct
{
u16 x;
u16 timingCnt;
u16 timing;
} Objet;

void updateObjet(Objet *obj)
{
obj->timingCnt++;
if(obj->timingCnt >= obj->timing)
{
obj->x++;
obj->timingCnt = 0;
}
}


Mais j'ai jamais trouvé ca terrible comme solution ...

Mollusk
06/02/2006, 17h03
je ne suis pas sur que les fixed point te viennent tellement en aide là, c'est plutot pour gérer des position que c'est utile

Nesgba
06/02/2006, 17h25
je ne suis pas sur que les fixed point te viennent tellement en aide là, c'est plutot pour gérer des position que c'est utile
justement, lui il gere le deplacement de ses sprite selon un timming qu'il modifie selon la vitesse qu'il veut attribuer a son sprite.
ca ressemble un peu au principe des fixed points mais en beaucoup moin propre :ph34r:
va voir le topic qu'avai fait arcadia sur l'ancien topic sur les trajectoires c'est super instructif et tu trouvera ton bonheur ;)

thoduv
06/02/2006, 17h29
Une autre petite question pour les pros de l'optimisation (c'est bon j'entends Nesgba qui arrive) :
que vaut-il mieux utiliser comme type pour les variables "générales" ? 8 bits (je pense pas quand même), 16 bits (ce que j'ai tendance à faire) ou 32 bits ? sur Gba ? sur Ds ?

EDIT: Et pour les valeurs à vocation booléene (on/off, oui/non, 1/0) ?

Mollusk
06/02/2006, 17h36
nes, autant pour moi, ca m'apprendra à pas regarder le code en entier... J'ai vu timer, je pensais à genre un compte de secondes ou autres, donc je ne voyais pas l'intéret... Mais effectivement c'est exactement ca, je sors :s

Sinon, pour les variables générales c'est vraiment au cas par cas !
Je veux dire, 8bit c'est super limité (0-255 ou -128-127), mais pour un menu avec juste 4 options c'est assez... En général je dirais que s16 devrait suffir, mais bon.

Pour les bool ? Pas compris, moi j'ai bool... non ?

thoduv
06/02/2006, 17h39
bool n'existe (n'est pas censé exister) pas en C.
Ce que je voulais savoir c'était au niveau de la rapidité d'accès et de l'optimisation CPU.

Nesgba
06/02/2006, 17h48
les bool existent pas ce sont des unsigned char cachés donc bon.

pour les variables ca depend ce que tu veut en faire elles sont toutes lues et incrementés a la meme vitesse.
donc si tu as pas besoin de valeurs negatives prend des unsigned short c'est celle qui sert le +.
evite a tout prix les float. (mais je me repete la >_< :p )
eh aretez de me prendre pour un pervert de l'optimisation :( c'est pas de ma faute si la gba est pas super puissante. :whst:

si je vois un code avec une division sur un flotant je fait une crise cardiaque :w00t:

thoduv
06/02/2006, 18h08
Ok... Donc si je veux utiliser que des int dans un souci de portabilité ca devrait pas poser de problèmes.

Une question un peu stupide : qu'est-ce qui est aà priori plus rapide :
b = a*3;
ou
b = a+a+a;
?

Mollusk
06/02/2006, 18h15
il me semble que l'addition est plus rapide, mais nes, expert en la matière nous le dira... mais je pense qu'on chipotte un peu là :p

Et sinon, je me suis toujours demandé, le compilo compile tout ca pareil ou pas :

x ++;
x+= 1;
x = x+1;

?

thoduv
06/02/2006, 18h18
il me semble que l'addition est plus rapide, mais nes, expert en la matière nous le dira... mais je pense qu'on chipotte un peu là :p

Et sinon, je me suis toujours demandé, le compilo compile tout ca pareil ou pas :

x ++;
x+= 1;
x = x+1;

?

L'optimisation c'est de toute facon du chipotage non ? :ph34r:

A mon avis le compilo est pas mal foutu au point de compiler differement ces trois trucs Mollusk ! :whst:

Mollusk
06/02/2006, 18h21
j'espère bien :p simple curiosité... Perso, je préfère x++ parce que je suis une larve qui a pas envie de trop taper...

Nesgba
06/02/2006, 18h27
thuoduv: L'optimisation c'est de toute facon du chipotage non ?

tu dit ca parcque tu as jamais poussé la gba ou la nds a fond ? :)
si tu veut etre le plus libre possible dans les possibilités de ton moteur de jeu tu est obligé de "chipotter".
moi si je peut afficher quelques flocons de neige soft en + parcque j'ai bien optimisé ailleur je suis tres content, mais apres ca depend ce que tu cherche a faire quand tu crée un jeu.

si tu fait un tetris ca serai bete de te prendre la tete pour ca, mais si tu attaque un moteur 3D soft ou un moteur 2D a la "sonic by brunni" tu as plutot interet >_<

Mollusk
06/02/2006, 18h35
c'est marrant, j'ai fait un tetris et pourtant j'ai cherché à l'optimiser à mort...

Nesgba
06/02/2006, 18h37
c'est marrant, j'ai fait un tetris et pourtant j'ai cherché à l'optimiser à mort...
oups je savais pas promis, je retire ce que j'ai dit :ange:

thoduv
06/02/2006, 19h11
thuoduv: L'optimisation c'est de toute facon du chipotage non ?

tu dit ca parcque tu as jamais poussé la gba ou la nds a fond ? :)
si tu veut etre le plus libre possible dans les possibilités de ton moteur de jeu tu est obligé de "chipotter".
moi si je peut afficher quelques flocons de neige soft en + parcque j'ai bien optimisé ailleur je suis tres content, mais apres ca depend ce que tu cherche a faire quand tu crée un jeu.

si tu fait un tetris ca serai bete de te prendre la tete pour ca, mais si tu attaque un moteur 3D soft ou un moteur 2D a la "sonic by brunni" tu as plutot interet >_<

C'était un peu de la provocation ! ^^
J'ai pas vraiment refléchi, parce que j'ai plutot l'habitude de jeux "lents" et d'applications, donc je suis pas tellement habitué à optimiser à fond ! :-'

Japi
06/02/2006, 20h49
Nes je t'aimes bien, mais je suis pas d'accord avec pleins de trucs que tu as ecris. ^^ la phrase de merde

L'instruction "mul r0,r1,#x" c'est une instruction du CPU, ça prend pas quelques disaines de cycle comme tu le dis mais un voire deux = bien moins que faire un:
mavariable = ((mavar2<<9)+(mavar2<<7)-(mavar2<<3)) (c un exmple, je sais pas combien ça fait mais bon, faire une multiplication avec 3 decalages et donc 2 additions ça arrive souvent, ben convertit en opération elementaires du CPU avec les instructions risc tu verras). par contre, si tu multiplie par une puissance de 2 ben ouais, là c'est mieux, ça depend donc de la situation, faut pas etre systematique.

"si je vois un code avec une division sur un flotant je fait une crise cardiaque", quand on utilise des floats, c'est pas pour faire beau, c'est parce que on a pas le choix, alors ya pas de question d'optimisation ou pas, ya un float et on fait avec.
Si y avait moyen de le virer c'est qu'on en avait pas vraiment besoin.

Pour les booleans en C, ya pas en tant que tel mais tu peux adresser sur un bit en concatenant apres par paquet de 8, donc au final, en fonction de la situation, si t'as des variables qui s'y pretent bien (genre 8 booleans) tu peux creer un paquet et là, c'est interressant.

Japi
06/02/2006, 20h57
A mon avis le compilo est pas mal foutu au point de compiler differement ces trois trucs Mollusk ! :whst:

t'as trop raison, le compilo, il sert à optimiser, c'est son boulot de repérer les sequences connu et de les transformer dans le code ASM le plus approprié et ça fait des années que des mecs bossent dessus, donc bon, dans 99% des cas, il optimise mieux que nous.

Mollusk
06/02/2006, 21h09
"si je vois un code avec une division sur un flotant je fait une crise cardiaque", quand on utilise des floats, c'est pas pour faire beau, c'est parce que on a pas le choix, alors ya pas de question d'optimisation ou pas, ya un float et on fait avec.
Si y avait moyen de le virer c'est qu'on en avait pas vraiment besoin.

Toi t'as jamais regardé les codes des autres ! Le nombre de gars qui utilise des floats que pour des nombres entiers parce qu'ils ont utilisé que des floats partout, etc... Parfois tu vois des trucs qui font peur, je le comprends mon petit nes.

Quand j'ai un mec qui m'envoie un truc parce qu'il a une fonction PAlib qui bug et que je vois comment c'est codé, j'ai envie d'effacer/changer la moitié de son code tellement c'est horrible parfois !

T'as meme des trucs du genre


if(Stylus.Held et stylet dans cette zonne..){...}
if(stulus.held et stylet dans autre zeon){...}

parfois 0-20 fois de suite, lol... Ca serait pas plus simple de sortir le stylus.held ??? et des else ??

Japi
06/02/2006, 21h53
oui oui, tu peux faire un add avec un lsl dedans pour combiner une addition et un decalage en une instruction mais la dessus ya pas de soucis.
Moi aussi j'utilise les dacalages mais dans les zones critiques et mon avis sur la question c'est que avant de passer aux astuces et autres decalages, faut dejà coder correctement (et je m'inclue dans le tas).
J'avais lu un truc pas mal fait qui disait:
1) prendre un BON compilo
2) apprendre à bien coder
3) supprimer les trucs qui serve à rien
4) eviter de faire des trucs qui servent à rien, je l'ai dejà dit mais bon!!! ^^
5) benchmarker pour voir les zones critiques
6) utiliser de l'optimisation avec par exmple : regarder l'asm produit par le compilo et
analyser les trucs qui peuvent etre mieux fait.
ça venait que à la fin, ya dejà pas mal de chose à faire et faut commencer par le debut. Pas la peine de mettre des << comme un fou alors que à coté on a fait n'importe quoi.

pour l'histoire de la multiplication, je voulais juste dire que dans certains cas, abusé des << est peut-etre plus lent qu'une bonne MUL selon le chiffre que tu multiplie mais pas les puissances de deux et autres evidemment.

Brunni
06/02/2006, 21h53
[Edit] Sorry, erreur de manip, j'ai posté en double, donc j'en ai supprimé un, Japi répondait en fait à celui-ci.

Japi> Heu non, la multiplication peut bien demander une dizaine de cycles selon les cas. Toutes les instructions ne prennent pas un cycle, même si elles sont directement codées dans le processeur.
De plus, en mode ARM (32 bits), les décalages sont supportés directement sans pénalité de cycle, par exemple, tu peux faire:
add r0,r1,r2,lsl r3
Ca donne: r0 = r1 + (r2 << r3), tout ça en 1 cycle si je ne m'abuse, ce qui peut améliorer à fond la vitesse si tu sais t'en servir. Mais rêve pas, c'est pas le compilo qui arrivera à te générer ça! :p
Quand tu connais un minimum l'ASM et que tu vas voir ce que ce trouffion de compilo te génère, tu tombes à la renverse... :berk: (donc dans le fond je comprends Nes, et même si tous les programmes n'ont pas besoin d'être optimisés, quand tu y as goûté c'est un vrai plaisir!).
Mollusk> variable++ pourrait être meilleur sur certaines plate-formes, lorsqu'il est utilisé dans des expressions. Je ne sais pas sur GBA, mais sur un 68000 par exemple, tu peux faire:
move.w d0, (a7)+
Ce qui équivaut à (*a7)++ = d0, en une instruction, et donc ceci: *ptr++ = 0 peut-être plus rapide que *ptr = 0; ptr++; (et dans ce cas il pourra optimiser, mais pas toujours, mais c'est de l'optimisation extrême).

Japi
06/02/2006, 21h59
Je me suis pas tappé le bouquin sur l'arm7tdmi pour faire le malin, j'utilise ceci.
De toute façon, les topics optimsiations sont tjrs sources de polemiques parce que dans tel ou tel situation, chacun peut avoir raison surtout quand ça se joue sur des cas particulier et à des nano seoncdes de différence.

Mollusk
06/02/2006, 22h02
Japi, des nanosecondes certes, mais plusieurs dizaines de milliers de fois par frame ca commence à faire :p

Japi
06/02/2006, 22h07
lol ^^ je l'attendais celle là!

sortie de son contexte bien comme il faut et tout ^^

Nesgba
06/02/2006, 22h25
lol ^^ je l'attendais celle là!

sortie de son contexte bien comme il faut et tout ^^

petit exemple tout bete:
dison que tu as un hbl de lancé et que ton code consomme deja pas mal de ressources, si tu met une instruction de ce type pour te faire un joli fond (enfin pas tres jolis dans ce cas la ca donne un gris bien degeu :berk: )
if(loop>=0 && loop<160) IRIS_Palette[0] = IRIS_RGB(((loop+20)/8), ((loop+15)/8), ((loop+10)/8)) ;
je peut te dire que tu la sent bien passer celle ci :D
alors qu'avec un truc comme c'est beaucoup mieu

if(loop>=0 && loop<160) IRIS_Palette[0] = IRIS_RGB(((loop+20)>>3), ((loop+15)>>3), ((loop+10)>>3)) ;

Japi
06/02/2006, 22h30
8 ne serait pas une puissance de deux?
genre comme un 2^3?
donc oui, là evidemment, ya pas photo.

Mollusk
06/02/2006, 23h48
Nes, Japi a jamais dit le contraire, c'est pour les convertions en additions+multiplications itératives qu'il disait...

Nrx
07/02/2006, 00h27
/me resiste pour ne pas participer a cette discussion...

Perso j'aime bien optimiser mon code (beh oui, sinon ca me rend malade !), mais j'espere que tout le monde sera d'accord pour dire qu'il faut commencer par utiliser les bons algos ! C'est meme souvent plus important que le code lui meme.

Un exemple ? Le pathfinder : si vous imaginez une solution toute bancale, ce sera surement moins bien qu'un bon vieux A*... Et dans votre implementation du A*, ce ne sont pas des listes chainees qu'il faut, mais des Heap et des BST/Direct Address...

A quand un petit concours ?? La resolution d'une grille de Sudoku serait un bon sujet. Ou alors l'affichage d'un cube en 3D. Ou je ne sais pas quoi...! (mais merci d'attendre que j'ai recupere mon PC principal - la je suis sur mon mini-laptop, et ce n'est pas genial pour coder !)

Japi
07/02/2006, 00h29
Ouais, il disait ça pour m'enerver un peu et ma reponse etait dans le même style ^^, on se battait joyeusement sur ce theme en même temps sur MSN, lol! A savoir à qui aurait le dernier mot sur un topic sans fin ^^

Nesgba
07/02/2006, 00h31
Nes, Japi a jamais dit le contraire, c'est pour les convertions en additions+multiplications itératives qu'il disait...
si il l'avai dit :p

mais meme, a ton avis lequel sera plus rapide ?

if(loop>=0&&loop<160)IRIS_Palette[0]=IRIS_RGB(((loop+20)*160),((loop+15)*160),((loop+1 0)*160)) ;

if(loop>=0&&loop<160)IRIS_Palette[0]=IRIS_RGB((((loop+20)<<7)+((loop+20)<<5)),(((loop+15)<<7)+((loop+15)<<5)),(((loop+10)<<7)+((loop+10)<<5))) ;


toute facon japi il comprend rien a la prog :ph34r: :w00t:

Mollusk
07/02/2006, 00h35
Nrx, sudoku solver :p Je testerais bien la vitesse de ma solution, parce que sur DS elle met largement moins d'une seconde (sur ému) à résoudre la grille difficile... Quand je vois ce que certains ont fait sur PC : remplir au hasard et garder les bonnes réponses... faut etre taré ! Mon code est super court et utilise les techniques de sudoku de bases qu'on trouve dans les bouquins, mais appliqué en algo... donc c'est super rapide :p

Nesgba
07/02/2006, 00h40
A quand un petit concours ?? La resolution d'une grille de Sudoku serait un bon sujet. Ou alors l'affichage d'un cube en 3D. Ou je ne sais pas quoi...! (mais merci d'attendre que j'ai recupere mon PC principal - la je suis sur mon mini-laptop, et ce n'est pas genial pour coder !)
pas la peine on va tous se faire roxer par mikegba avec son asm la <_< meme si on s'y met a plusieurs XD
mais c'est une bonne idée quand meme :)

Nrx
07/02/2006, 00h45
mais meme, a ton avis lequel sera plus rapide ?

if(loop>=0&&loop<160)IRIS_Palette[0]=IRIS_RGB(((loop+20)*160),((loop+15)*160),((loop+1 0)*160)) ;

if(loop>=0&&loop<160)IRIS_Palette[0]=IRIS_RGB((((loop+20)<<7)+((loop+20)<<5)),(((loop+15)<<7)+((loop+15)<<5)),(((loop+10)<<7)+((loop+10)<<5))) ;

Ben moi j'aurais carrement fait :
if(loop>=0&&loop<160)
{
loop160=loop*160;
IRIS_Palette[0]=IRIS_RGB(loop160+20*160,loop160+15*160,loop160+10 *160);
}
Et puis si "loop" est de type "unsigned", alors il est inutile de faire "loop>=0"... et s'il est de type "signed", on peut faire "if((unsigned short)loop<160)" car un nombre negatif caste sur un unsigned devient tres grand (et donc superieur a 160), du coup un seul test suffit.

Enfin, si la variable "loop" est juste incrementee a chaque cycle, on peut la supprimer et n'utiliser que "loop160" :
if((unsigned short)loop160<160*160)
IRIS_Palette[0]=IRIS_RGB(loop160+20*160,loop160+15*160,loop160+10 *160);

// quand il faut incrementer "loop" on fait :
loop160+=160;
...mais bon, je n'ai pas teste :-'.

Nesgba
07/02/2006, 00h51
petite erreur

if(loop>=0&&loop<160)
{
loop160=loop*160;
IRIS_Palette[0]=IRIS_RGB(loop160+20,loop160+15,loop160+10);
}

tu veut dire, mais je montrai ca pour le principe :)

Nrx
07/02/2006, 01h01
petite erreur

if(loop>=0&&loop<160)
{
loop160=loop*160;
IRIS_Palette[0]=IRIS_RGB(loop160+20,loop160+15,loop160+10);
}

tu veut dire, mais je montrai ca pour le principe :)
Heu...

(loop+20)*160 = loop*160+20*160 = loop160+20*160

=> pas d'erreur !

En tout cas ce que je voulais ajouter a ta demonstration, c'est qu'il est preferable :
- de factoriser (en l'occurrence la multiplication de la variable),
- de jouer avec les cast pour supprimer un test lorsque c'est possible,
- de finalement supprimer la multiplication en ne gardant que la variable dont on a vraiment besoin ("loop160" dans ce cas).

Je precise au passage (pour ceux qui ne suivraient pas) que les multiplications qui restes ne coutent rien (optimisees par le compilateur puisqu'il s'agit de constantes).

Voila !:)

Nesgba
07/02/2006, 01h08
ah je pensai avoir mal pigé ton code, mais pourquoi tu rajoute une multiplication ? ...
tu crois vrament que tu gagne en multipliant une variable plutot qu'une operation sur une variable ? parcque une multiplication de + rien que pour ca j'aurai hesité moi. merci pour la demo ;)

Mollusk
07/02/2006, 01h10
je vois pas de multiplication sur variable moi

Nrx
07/02/2006, 01h18
ah je pensai avoir mal pigé ton code, mais pourquoi tu rajoute une multiplication ? ...
tu crois vrament que tu gagne en multipliant une variable plutot qu'une operation sur une variable ? parcque une multiplication de + rien que pour ca j'aurai hesité moi. merci pour la demo ;)
Dans le code original il y avait 3 multiplications :

IRIS_Palette[0]=IRIS_RGB(((loop+20)*160),((loop+15)*160),((loop+1 0)*160));

Donc je propose de les remplacer par une seule multiplication en utilisant une variable supplementaire :
loop160=loop*160;

...et ceci me donne l'opportunite ensuite de supprimer carrement "loop", et donc meme la multiplication ! (a condition bien sur de maitriser les modifications faites sur "loop" : il faut modifier "loop160" de facon adequate)

Japi
07/02/2006, 01h35
Nrx RuLeZ dA WoRlD!! ^^

Japi
07/02/2006, 01h39
je vois pas de multiplication sur variable moi

Sur constante, Nes ^^

attend je te la refais ^^!

((20)<<7)+((20)<<5)) tu l'as voit là? ^^ ou comment se precipiter sur un signe "*" et le passer en << pour penser gagner en cpu!

elle est là 20*160 lol

Mollusk
07/02/2006, 01h43
Japi, nes parlait d'en rajouter une sur variable... j'ai bien vu sur constante, mais je vois pas où il aurait vu une sur variable...

Japi
07/02/2006, 01h47
oui, je sais que tu as vu, d'ailleurs c'est pour ça que je te citais! c'etait une petite reponse à Nes pour son pic quelques post plus haut ^^

Mollusk
07/02/2006, 10h09
oulah, pas frais le mollusk :s

Bodom-Child
07/02/2006, 10h22
Quand j'ai un mec qui m'envoie un truc parce qu'il a une fonction PAlib qui bug et que je vois comment c'est codé, j'ai envie d'effacer/changer la moitié de son code tellement c'est horrible parfois !

Tu parles de moi là :-' ...? C'est vrai que j'ai un peu abusé des switch/case mais bon, c'est tellement plus simple à lire :p .

Nesgba
07/02/2006, 10h31
Sur constante, Nes ^^
attend je te la refais ^^!
((20)<<7)+((20)<<5)) tu l'as voit là? ^^
ah ca y est je pige mieu la d'un coup :D
mais veuillez cesser avec votre constante Oo, c'est une variable.

MIKEGBA
07/02/2006, 10h41
:D et ben dis donc, y'a de l'ambiance au moins ici !!!

quel fight !!!:bravo:

Mollusk
07/02/2006, 10h58
Bodom, non, pas du tout :) Je dirais rien parce que j'avoue que j'ai pas regardé ton code, juste assez pour corriger le/les bugs de PAlib... Mais si tu veux je peux regarder, lol.

C'était des personnes sur PAlib.com essentiellement

Dr.Vince
07/02/2006, 12h33
Vous êtes vraiment une bande de psychopate du code.
En tout cas Nrx avait raison, y a pas que les optimisations, l'algorithmique est très importante également.

Sinon moi j'aurais remplacé :


if(loop>=0&&loop<160)
{
loop160=loop*160;
IRIS_Palette[0]=IRIS_RGB(loop160+20*160,loop160+15*160,loop160+10 *160);
}

par :


if(loop>=0&&loop<160)
{
loop160=loop*160;
IRIS_Palette[0]=IRIS_RGB(loop160+3200,loop160+2400,loop160+1600);
}

Mollusk
07/02/2006, 13h01
le compilo le fait pour toi Dr

Dr.Vince
07/02/2006, 13h54
c'était pour optimiser le temps de compilation :p :p

Nesgba
07/02/2006, 14h08
je savai que si je mettai 3 multiplications par 160 je prenai le risque que quelqun me crie dessu mais j'avai pas envie de convertir d'autres nombres en decalages, donc bon c'etait juste pour expliquer, la prochaine fois je mettrai des nombres differants comme ca y'aura plus de problemes :)

puis faut pas faire aussi confiance au compillo, moi je part du principe qu'il fait rien, je me fait chier mais au moin je prend pas de risques :p

thoduv
08/02/2006, 20h47
Une opération sur constante ... C'est pas fait par le compilo ca ?
Par exemple, si par souci de lisibilité je fais :
a= 8<<10;
Le compilo va rajouter une instuction pour calculer 8<<10 ou va remplacer directement par 2000h ?

Mollusk
08/02/2006, 20h50
thoduv, normalement si. Mais nes il a appris à coder à l'époque où t'avais pas de compilo ;)

thoduv
08/02/2006, 20h52
Ouais ok, parce que dans le cas d'un changement sur un registre, avoir un code du style REG &= ~(1<<7) est plus clair que REG &= 0xFF7F ...

Mollusk
08/02/2006, 21h03
Par contre j'ai une question :

extern inline u8 FaireTruc(u8 var1, u8 var2){
return(var1*var2);
}
Si je fais var3 = FaireTruc(2, 3); ca va m'optimiser ca en var3 = 6 directement ? Et c'est équivalent à
#define FaireTruc(var1, var2) ((var1)*(var2)) ?

Je demande, parce que quand j'ai fais des tests sur gba pour comparer le meme code entre une macro et une fonction inline, la macro était un tout petit poil plus rapide :s Mais la fonction inline ca fait plus propre

Nrx
08/02/2006, 21h15
A mon avis le compilo ne fait pas l'optimisation dans le cas d'une fonction inline (alors qu'il optimisera bien le code equivalent ecrit sous forme de macro). Une difference majeure entre une fonction (inline ou pas) et une macro, c'est que les arguments des fonctions sont types, et qu'il peut donc y avoir un cast...

Mollusk
08/02/2006, 21h39
c'est ce que je pensais nrx... sauf que je savais pas trop comment mettre les mots, lol. J'ai d'un point de vue pratique, s'il a les valeurs exactes, le compilo devrait pouvoir s'occuper du type directement, non ?
Ou alors il va convertir la inline en
u8 var1 = premiere valeure
u8 var2 = deuxième valeure
var3 = var1+var2
?

Nrx
08/02/2006, 22h00
Je ne veux pas dire de betise - il faudrait faire le test (i.e. verifier le code asm genere), mais sans parler des problemes de cast je pense que dans le cas d'une fonctione inline le compilo fera bien une operation (multiplication dans ton 1er exemple)... alors qu'avec une macro il remplacera le calcul par son resultat.

Pour ce qui est du cast, voici un exemple :
Je n'ai pas essaye, mais je pense que si on definit :inline u8 Test1(u8 var1,u8 var2)
{
return(var1*var2);
}

#define Test2(var1,var2) ((var1)*(var2))alors le comportement des tests suivants ne sera pas le meme :if(Test1(256,3))
{
// le resultat de l'appel a Test1 serait different de 0 ? ce n'est pas vrai !
}
if(Test2(256,3))
{
// le resultat de l'appel a Test2 est bien different de 0 !
}

Mollusk
08/02/2006, 22h07
ca je suis d'accord, j'ai donné un exemple avec un u8 parce qu'on s'en sert souvent pour les sprites ou les fonds (donc il faut en fait rajouter un petit &255 à la macro éventuellement). De meme que si je n'avais pas mis de parenthèses dans la macro, on aurait des surprises en faisant genre Test(a+b, c), qui donnerait a+(b*c) au lieu de (a+b)*c...

Mollusk
09/02/2006, 10h17
Et qu'en est-il de l'ordre des multiplications entre variables ? Il vaut mieux mettre celle qui sera généralement plus petites en quelle position ?

MIKEGBA
09/02/2006, 11h07
Et qu'en est-il de l'ordre des multiplications entre variables ? Il vaut mieux mettre celle qui sera généralement plus petites en quelle position ?


la plus petite en dernier normalement.

le nombre de cycle que prend un mul dépend de la taille de la derniere variable, 1 cycle interne par tranche de 8 bits significatifs

exemple: si derniere variable = 200 = 8 bits sinificatifs = 1 cycle interne

si derniere variable = 513 = 2 tranches de 8 bits significatifs= 2 cycle interne


au pire une multiplication prend donc 4 cycles internes si les 32 bits sont significatifs.

Mollusk
09/02/2006, 12h01
merci beaucoup mikegba, c'est exactement ce que je voulais savoir :)
et donc si j'ai genre s32 ma var = (u8)var1 * (u32)var2;
le compilo va l'optimiser en inversant l'ordre ou alors il va faire son blaireau ?

Mollusk
09/02/2006, 14h58
au fait, complètement HS, mais je voulais pas ouvrir un topic pour ca :
vous pensez quoi de wintermute ?? (ouais, bizarre comme question, simple curiosité on va dire ;))

Japi
09/02/2006, 22h12
je sais pas ce que c'est.

EDIT : ça? http://www.dead-code.org/index2.php/en

Mollusk
09/02/2006, 22h15
Euh, non, c'est le mec qui fait devkitpro (tu connais ?) ;)
Son pseudo c'est genre wntrmute me semble

Dr.Vince
10/02/2006, 01h27
ptite question comme ça.
niveau perf, y a-t-il une différence entre :
while(test(x)){
x--;
}

et


while(test(--x)){}

DJP
10/02/2006, 01h35
ptite question comme ça.
niveau perf, y a-t-il une différence entre :
while(test(x)){
x--;
}
et


while(test(--x)){}

et entre un :


x=0;
while(x<100){
blabla;
x++
}

et


for(x=0;x<150;x++){
blabla;
}

Mollusk
10/02/2006, 13h13
Pour celle de DrVince, je ne suis pas sur que le compilo optimise pareil, donc la deuxième serait peut-etre plus rapide. Pour celle de phantom, je dirais que c pareil par contre

Brunni
10/02/2006, 15h24
et entre un :
x=0;
while(x<100){
blabla;
x++
}
et
for(x=0;x<150;x++){
blabla;
}
Non la deuxième sera plus lente car il y aura 150 itérations et seulement 100 pour la première. Et la première ne se compilera pas (parse error before '}'). :whst:
Plus sérieusement, normalement c'est égal car les deux notations correspondent: un for(1;2;3) 4; fait bien:
1;
while (2) {
4;
3;
}
Une fois compilé.

Dr. Vince> Les deux ne font pas la même chose! --x est une pré-décrémentation, donc si tu fais:
x=5;
affiche(--x); -> 4
affiche(x); -> 4
Il faut une post-décrémentation dans ton cas pour que ça corresponde:
x=5;
affiche(x--); -> 5
affiche(x); -> 4
Mais à part ça il ne devrait pas y avoir de différence. En fait, ce n'est qu'en cas de "bug" du compilo qu'on peut voir des différences de perfs entre les notations. Après tout dépend de ce que tu préfères niveau lisibilité... ;)

Mollusk
10/02/2006, 15h52
ah, j'avais lu x-- moi, j'ai du mal :s pourtant j'ai regardé 2 fois en plus pour etre sur... :s

Mollusk
02/03/2006, 12h57
Un petit up pour une question :

void FaireTruc(u8 numero){
tableau[numero].x += tableau[numero].vx;
tableau[numero].y += tableau[numero].xy;
etc...
}

et

void FaireTruc(typetableau *truc){
truc->x += truc->vx;
truc->y += truc->xy;
etc...
}

Niveau performances ca change beaucoup ou pas ?

edit : dans le meme genre, entre utiliser

pointeur[0] = truc;
pointeur[1] = autre truc;
pointeur[2] = 3ème truc;
etc...

ou

*pointeur = truc;
pointeur++;
*pointeur = truc2;
etc...

?

Gwoin
02/03/2006, 19h25
il ne doit pas y avoir reellement de différences.
Dans le meilleur des cas, il vaudrait surement mieux passer directement le pointeur sur l'objet au lieu du pointeur sur la liste d'objets.

Dans tout les cas il faut faire un appel du type "tableau[numero]", soit dans la fonction, soit juste avant celle-ci.

Maintenant, en en ce qui concerne le cas général, je ne suis pas convaincu de la reelle différence de vitesse.

Il me semble par contre qu'utiliser des pointeurs et plus long à l'execution que sans.

DJP
02/03/2006, 19h44
Je viens de découvrir comment generer un vecteur dynamiquement, c'est le pied, donc pour ceux qui veulent le code :


Vecteur * new_vecteur(int taille){
int i;
Vecteur *p;
p=(Vecteur *)malloc(sizeof(Vecteur )*taille);
for (i=0;i<taille;i++){
p[i]=0;
}
return p;
}
Voilà, c'est "simple" mais ça peut grandement servir pour le stockage de données de taille variable.

Edit : biensur, votre vecteur ça peut etre n'importe quoi, des int, des struct etc...

Nesgba
02/03/2006, 20h04
Niveau performances ca change beaucoup ou pas ?

edit : dans le meme genre, entre utiliser

pointeur[0] = truc;
pointeur[1] = autre truc;
pointeur[2] = 3ème truc;
etc...

ou

*pointeur = truc;
pointeur++;
*pointeur = truc2;
etc...

?

moi je dirai que la 2eme est plus lente, puisque tu as une incrementation en +, mais je peut me tromper.

Mollusk
02/03/2006, 22h26
tu as une incrémentation en plus, mais pour faire pointer[2], le compilo doit faire adresse du pointer + 2 = truc, donc à voir...
j'aurai aussi pu rajouter (u32*)(pointer+2) = truc;

thoduv
02/03/2006, 23h10
Faut aussi voir que *(type*)(p+x)=valeur; c'est vraiment dégueu et ca rend le code confus, pareil pour les incrémentations (:berk:). Même s'il s'avérait que c'est plus lent, je pense qu'il FAUT utiliser p[x]=valeur; si on veut pas se retrouver avec un code incompréhensible par quelqu'un d'autre ou par soi-même...

Mollusk
02/03/2006, 23h31
dans mon cas c'est une routine de quelques lignes pour écrire le plus rapidement possible dans la VRAM, donc je m'en tape que ca soit pas super lisible, c'est dans les fonctions de PAlib et personne n'ira voir... C'est juste pour une optimiser une partie critique, en gros

DJP
03/03/2006, 00h15
dans mon cas c'est une routine de quelques lignes pour écrire le plus rapidement possible dans la VRAM, donc je m'en tape que ca soit pas super lisible, c'est dans les fonctions de PAlib et personne n'ira voir... C'est juste pour une optimiser une partie critique, en gros

Il y a toujours des optimisations auquelles on ne pense pas. Ballance direct ta fonction...

Mollusk
03/03/2006, 12h29
Il y a toujours des optimisations auquelles on ne pense pas.
C'est à dire que là le code commence à etre court... A part passer en asm (NON, je ne veux pas !!)... Je le poste dans pas longtemps

Mollusk
03/03/2006, 13h38
Exemple de code que je cherche à optimiser :

#define PA_16cPos(x, y) (((x>>3)*26*8) + y + 1)

ALWAYSINLINE void PA_16c8X4(u8 screen, s16 x, s16 y, u32 *image){
x += 8; y += 8;
u16 temp = (x&7)<<2;
u16 pos = PA_16cPos(x, y);
PA_Draw1632[screen][pos] |= (image[0]<<temp);
PA_Draw1632[screen][pos+1] |= (image[1]<<temp);
PA_Draw1632[screen][pos+2] |= (image[2]<<temp);
PA_Draw1632[screen][pos+3] |= (image[3]<<temp);
pos += (26*8); // Next columns
temp = 32-temp;
PA_Draw1632[screen][pos] |= (image[0]>>temp);
PA_Draw1632[screen][pos+1] |= (image[1]>>temp);
PA_Draw1632[screen][pos+2] |= (image[2]>>temp);
PA_Draw1632[screen][pos+3] |= (image[3]>>temp);
}

Il me permet d'afficher des objets de 8x4 sur un fond en 4bit (tiles).
J'ai laissé les 26*8 par soucis de clarté, mais a priori ca ne change rien... Je ne fais qu'ajouter des bits sans faire de &= avant afin d'accélérer au maximum les choses (je ferais une fonction avec mask en plus). Ca mer permet de plotter 8 pixels d'un coup, donc c'est assez rapide... (en organisant bien ma palette ca passe bien)
J'ai meme testé de copier l'image en ram pour etre sur que ce soit rapide, mais ca ne change pas grand chose...

Des idées pour optimiser ca un peu plus ? :)

Brunni
03/03/2006, 14h04
Si c'est pour du texte, essaie de regarder mon projet GBA, peut-être que tu y trouveras ton bonheur. :)
Mais ton code actuel n'est pas si mal :p
[Edit] Y'a aussi mon "EZ Loader perso" (si tu t'en souviens ;)) qui contient des routines de texte encore plus optimisées, mais je sais pas où il est passé :(

Mollusk
03/03/2006, 14h21
C'est pas pour du texte à la base mais pour tout et n'importe quoi (mais ca va aussi servir pour du texte)

Nesgba
03/03/2006, 14h23
bah c'est mieu optimisé que mon pavé deja (mais je l'ai volontairement faite generique aussi)

sinon je l'ai ta source de ton loader brunni si tu le veut ;)

exemple: (ca fait au moin 6 mois que j'y ai pas touché donc pas de moqueries !)

/*################################################# #################################################
## Fonc: AfficheSpriteSoft8x84bit_MODE0
## Def : affiche un tile de 8x8 mode 16 couleurs en plottant jusqu'a 8 pixels a la fois
################################################## ################################################*/
void IRIS_IN_IWRAM AfficheSpriteSoft8x84bit_MODE0(u8 *tableau, u16 x, u16 y, u8 largeur, u8 particule, u8 largeurParticule, u8 hauteurParticule, u8 num)
{
u8 number ;
u32 *adresse, ligne, *valeur=0 ;
u32 masque = 0xffffffff ;
u8 decalage ;
u32 indice ;
u8 offset_y ;

for (offset_y=0; offset_y<hauteurParticule; ++offset_y, ++y){
// selon la particule a afficher
indice = (particule<<5) + (offset_y<<2) ;

// selon le nombre de pixels a afficher
ligne = tableau[indice] ;
if (largeurParticule<=8 && largeurParticule>2) ligne+=(tableau[indice+1]<<8) ;
else if (largeurParticule<=8 && largeurParticule>4) ligne+= (tableau[indice+2]<<16) ;
else if (largeurParticule==8) ligne+= (tableau[indice+3]<<24) ;

adresse = (u32*)((void*)IRIS_BG[num].CharBaseBlock + (((x&~0x7) + (y&~0x7)*largeur + (y&0x7))<<2)) ;
decalage = ((x&0x7)<<2) ;

*adresse &= ~(masque<<decalage) ; // suppression des pixels sur lesquels on va dessiner
*adresse |= (ligne<<((x&0x7)<<2)) ; // on ajoute les pixels

decalage = 32 - decalage ; // le décalage est différent dans l'autre mosaïque
adresse += 8 ; // on change de mosaïque
*adresse &= ((masque >> decalage) << decalage) ;
*adresse |= (ligne>>decalage) ;}
}


sinon un petit ligne=(tableau[indice+1]<<8)+(tableau[indice+2]<<16)+(tableau[indice+3]<<24) ;
pour en foutre 8 d'un coup c'est tres efficace ;)

Mollusk
03/03/2006, 14h34
ca sera pas assez rapide pour moi, j'ai fait des fonctions en inline spécifiques par taille (de 8x4 à 16x16) histoire d'optimiser à mort, et j'ai organisé mes boucles pour pas avoir de if inutiles ^^

Nesgba
03/03/2006, 14h39
ca sera pas assez rapide pour moi, j'ai fait des fonctions en inline spécifiques par taille (de 8x4 à 16x16) histoire d'optimiser à mort, et j'ai organisé mes boucles pour pas avoir de if inutiles ^^

quand j'aurai un peu de temp je me pencherai dessu, en tout cas sache que en asm c'est allucinant la puissance que tu peut tirer de ce genre de routine, mikegba doit afficher ses tiles presque 2 fois plus vite que moi ce malade, pourtant elle est pas si degeu ma routine.

me>desespéré... vais me pendre tien >_<

Mollusk
03/03/2006, 14h48
ben là c'est assez rapide, je peux effacer les 2 écrans puis écrire 800 images de 8x4 (ou genre 500 de 8x8) avant que le VCount n'arrive à 0 (donc avant qu'il ne raffraichisse l'écran. Le copie DMA me prend environ 10Vcount par écran... Le but inavoué étant bien sur de se passer de double buffer (psycho power !) afin d'économiser en mémoire et en temps...

Autre solution (de tordu) : effacer la ligne déjà dessinée à l'écran (genre dans le hbl, effacer la ligne vcount-1...), ca m'éviterait de devoir effacer les écrans, mais ca me parait trop tordu/poussé/lourd ^^
edit : quoi que :p

Nesgba
03/03/2006, 15h03
ben là c'est assez rapide, je peux effacer les 2 écrans puis écrire 800 images de 8x4 (ou genre 500 de 8x8) avant que le VCount n'arrive à 0 (donc avant qu'il ne raffraichisse l'écran. Le copie DMA me prend environ 10Vcount par écran... Le but inavoué étant bien sur de se passer de double buffer (psycho power !) afin d'économiser en mémoire et en temps...

Autre solution (de tordu) : effacer la ligne déjà dessinée à l'écran (genre dans le hbl, effacer la ligne vcount-1...), ca m'éviterait de devoir effacer les écrans, mais ca me parait trop tordu/poussé/lourd ^^
edit : quoi que :p

heu tu parle de 2 ecrans c'est sur nds donc Oo tu t'est loupé dans tes chiffres ou tu fait des trucs a coté ?

parcque sur gba tu peut plotter 400/500 tiles environ, un ecran complet ca commence a ramer severe mais si je tombe a 20 fps je remplis presque 2 ecrans.
donc sur nds avec un proc 67mhz ca doit booster bien comme il faut !! :)

oui c'est malin mais tu imagine lancer une hbl avec un truc aussi lourd, tu as peur de rien toi :D

edit: oui c'est tordu et pas du tout rentable a mon sens (sauf si tu utilise deja la hbl) :p

Mollusk
03/03/2006, 15h08
Dans la hbl il n'y aurait que 34 u32 à mettre, ce qui me parait pas énorme... si ?

Sinon, je ne me suis pas loupé dans mes chiffres. C'est juste qu'entre la ligne 192 et la ligne 262 (la dernière) il faut que je fasse tourner mon vbl, mon effacage des 2 écrans, et l'écriture de tous les trucs... Donc ca prend quand meme du temps tout ca (environ 20 lignes rien que pour effacer, plus quelques lignes pour le vbl (j'anime des sprites en meme temps dans le vbl ^^), ce qui laisse pas énormément de temps pour plotter tout ca...