Sprites, adresse mémoire et gfxoffset

Démarré par ccc, 15 Août 2012 à 22:29:28

« précédent - suivant »

0 Membres et 1 Invité sur ce sujet

ccc

Bonjour,

Je vous soumets un nouveau probl?me sur lequel je bute en ce moment.
J'ai 3 sprites pour l'instant, un monstre, un ours et une "boulette". Je charge donc 3 images bmp, chacune des images contenant 9 étapes d'animation différentes (exactement comme dans l'exemple AnimatedSprite).

Donc pour charger mes sprites je fais la chose suivante
char sprTiles[9]={0,2,4, 6,8,10, 12,14,32};  // Remeber that sprites are interleave with 128 pix width,
oamInitGfxSet(&gfxpsrite, (&gfxpsrite_end-&gfxpsrite), &palsprite, 0, 0x4000, OBJ_SIZE16);
oamInitGfxSet(&gfxpours, (&gfxpours_end-&gfxpours), &palours, 1, 0x4000+(&gfxpsrite_end-&gfxpsrite), OBJ_SIZE16);
oamInitGfxSet(&gfxpboulette, (&gfxpboulette_end-&gfxpboulette), &palboulette, 2, 0x4000+(&gfxpsrite_end-&gfxpsrite)+(&gfxpours_end-&gfxpours), OBJ_SIZE16);


Je fais donc 3 oamInitGfxSet, chacun ? son propre id de palette, et je commence ? les rentrer en 0x4000 puis le prochain sera en 0x4000+la taille des précédent sprites.

Et ensuite pour les afficher je fais :


monster.gfx_frame = sprTiles[monster.anim_frame + monster.state*FRAMES_PER_ANIMATION ];
monster2.gfx_frame = 64+sprTiles[monster2.anim_frame + monster2.state*FRAMES_PER_ANIMATION ];
boulette.gfx_frame = 128+sprTiles[boulette.anim_frame + boulette.state*FRAMES_PER_ANIMATION ];
oamSet(0,  monster.x, monster.y, 3, monster.flipx, 0, monster.gfx_frame, 0);
oamSet(4,  monster2.x, monster2.y, 3, monster2.flipx, 0, monster2.gfx_frame, 1);
oamSet(8,  boulette.x, boulette.y, 3, boulette.flipx, 0, boulette.gfx_frame, 2);


Je décale donc de 64 pour le 2eme sprite, et de 128 pour le 3eme. Ce qui fait que la quatri?me étape d'animation du 1er sprite sera en 6, en 70 pour le 2?me et en 134 pour le 3?me.

Ca fonctionne au poil sous zsnes, sous bsnes j'ai un carré zébré ? la place de mon sprite de boulette, et sous no$snes le sprite de la boulette ne s'affiche pas du tout. 3 émulateurs différents et 3 rendus différents, je dois faire quelque chose de mal  :(
Sous les 3 émulateurs par contre les 2 permiers sprites s'affichent sans probl?me.

Je s?che complétement, j'ai relu 15 fois la partie "Sprite un vram" du wiki (http://www.portabledev.com/wiki/doku.php?id=sprites_en#sprites_in_vram) et il y a quelque chose qui m'échappe c'est certain  ???

Avec mes sprites de 16*16 je devrais ?tre dans ce cas l? :
CitationSimilarly, when using 16×16 sprites, there will be 8 sprites interleaved, and the ninth sprite will have to start after them at offset 1024
C'est pour ça qu'on passe de 14 ? 32 dans le tableau des offset j'imagine :
char sprTiles[9]={0,2,4, 6,8,10, 12,14,32};

J'ai essayé avec des tas d'offset différents, avec des adresses mémoires différentes, et le meilleur rendu que j'ai obtenu c'est avec le code indiqué plus haut, malheureusement il n'y a que zsnes qui semble en vouloir   :-\

Merci d'avance pour votre aide !

alekmaul

Je dirais que déj?, oamInitGfxSet doit ?tre unique, ensuite utilise directement dmaCopyVRam, sinon tu va changer l'adresse de base (cf le code source de la lib).
Pour les palettes, idem et ensuite oamSet te permettra de jongler avec les bonnes palettes, comme tu as fait en passe de 0 ? 1 puis 2.
Enfin, faut pas ouliber une chose ultra importante sur SNES, la copie vers la vram doit ?tre utilisée juste apr?s une VBL, donc, juste avant linit, commence par un WaitForVBlank() et SetBrightness(0) pour forcer la VBL.

Enfin, bonne idée de tester sous bsnes, c'est le seul qui est vraiment SNES compliant. Perso, je debug avec no$sns mais la validation finale est toujours avec bsnes avant de passer sur console.

ccc

Merci pour ton aide ! Mais j'ai peur d'avoir encore plein de questions  :-[

Si oamInitGfxSet n'est appelé qu'une seule fois je dois mettre tous mes sprites dans la m?me image j'imagine. Est-ce qu'il y une r?gle particuli?re pour construire cette image ?

En fait je peux peut-?tre m'inspirer du code de likemario.c pour le découpage :
// Init Map to address 0x1000 and Copy Map to VRAM
    bgSetMapPtr(1, 0x1000, SC_64x32);
    for (i=0;i<31;i++) { // 128 pixel height -> 128/8 = 16 2400 / 8 = 300
        u8 *ptrMap  = &map + 300*i*2; // 300 = map size x *2 because each entry is 16bits length
        if (i>=16) ptrMap  = &map + 300*5*2; // Init anything else with white line
        u16 ptrVRAM = 0x1000+i*32; // screen begin to 0x1000
        dmaCopyVram(ptrMap, ptrVRAM, 32*2); // copy row to VRAM
        dmaCopyVram((ptrMap+32*2), (ptrVRAM+32*32), 32*2); // copy row to VRAM
    }

La c'est pour la map mais le m?me principe doit ?tre le m?me non ?

Bon je vais essayer de digérer tout ça  ;)

alekmaul

non, non, tu mets pas tout dans la m?me images, il suffit que tu copie au bon endroit avec dmaCopyVRam.
Par exemple , si tu as 2 bitmaps, s1 et s2, voil? ce que tu peux faire :

dmaCopyVram(adrgfx_s1, adrenvramcopie, sizeof(s1gfx));
dmaCopyVram(adrgfx_s1 adrenvramcopie+sizeof(s1gfx),sizeof(s2gfx));

Ainsi, tu copie ? la suite du premier.
Tu peux aussi fixer l'adresse vram "en dur" mais attention ensuite pour bien adresser le bon numéro de gfxset pour les sprites.
Et en copiant comme ça, tu peux faire plein de sprites en 16 couleurs différentes en adressant ensuite avec oamSet la bonne palette :).

ccc

:'( J'y arrive toujours pas. Je suis un boulet je crois bien  :-[
Voil? ce que je fais :
u16 adrenvramcopie=0x4000;
unsigned char palEntry;
WaitForVBlank();
setBrightness(0);
dmaCopyVram(&gfxpsrite, adrenvramcopie, sizeof(gfxpsrite));
dmaCopyVram(&gfxpours, adrenvramcopie+sizeof(gfxpsrite),sizeof(gfxpours));
dmaCopyVram(&gfxpboulette, adrenvramcopie+sizeof(gfxpsrite)+sizeof(gfxpours),sizeof(gfxpboulette));
palEntry = (128+0*16);
dmaCopyCGram(&palsprite, palEntry, OBJ_SIZE16);
palEntry = (128+1*16);
dmaCopyCGram(&palours, palEntry, OBJ_SIZE16);
palEntry = (128+2*16);
dmaCopyCGram(&palboulette, palEntry, OBJ_SIZE16);


Il n'y a plus d'oamInitGfxSet.
Maintenant mes sprites sont remplacés par des polices de caract?res  ;D
Par contre les palettes des sprites sont bien initilialisées je les retrouve dans no$sns.
Je garde bon espoir de comprendre un jour ceci dit  :)

alekmaul

T'es un extrémiste toi  ;D , fallait laisser le premier oamInitGfxSet car il fait des trucs en plus  :P comme par exemple l'init de l'adresse des sprites et la taille de ces derniers ...

Voici le code de la fonction (que tu peux retrovuer sur googlecode aussi)

Citation
//---------------------------------------------------------------------------------
void oamInitGfxSet(u8 *tileSource, u16 tileSize, u8 *tilePalette, u16 paletteSize, u8 tilePaletteNumber, u16 address, u8 oamsize) {
   unsigned char palEntry;

   //setBrightness(0);  // Force VBlank Interrupt
   WaitForVBlank();
   
   // Init tiles
   dmaCopyVram(tileSource, (address >> 1), tileSize);
   
   // Init palette
   palEntry = (128+tilePaletteNumber*16);
     dmaCopyCGram(tilePalette, palEntry, paletteSize);

   // Update base adress if needed (16k aligned)
   REG_OBSEL = oamsize | (address >> 14);
}

ccc

Salut !
Je reviens ? la charge apr?s une petite pause, et je suis toujours bloqué avec cette histoire  :'(
J'en suis l? :
u16 adrenvramcopie=0x4000;
unsigned char palEntry;
WaitForVBlank();
setBrightness(0);
oamInitGfxSet(&gfxpsrite, (&gfxpsrite_end-&gfxpsrite), &palsprite, 0, adrenvramcopie, OBJ_SIZE16);
dmaCopyVram(&gfxpours, adrenvramcopie+sizeof(gfxpsrite),sizeof(gfxpours));
dmaCopyVram(&gfxpboulette, adrenvramcopie+sizeof(gfxpsrite)+sizeof(gfxpours),sizeof(gfxpboulette));
palEntry = (128+1*16);
dmaCopyCGram(&palours, palEntry, OBJ_SIZE16);
palEntry = (128+2*16);
dmaCopyCGram(&palboulette, palEntry, OBJ_SIZE16);

Un oamInitGfxSet pour les initialisations, deux dmaCopyVram pour les deux autres sprites, et deux dmaCopyCGram pour nos amies les palettes.
Les palettes ont l'air d'?tre OK (dans no$snes), mais les sprites en dehors du premier sont toujours invisibles.
J'ai fait une méga boucle de la mort pour afficher les 128 sprites et idem le 1er est l? mais pas les deux autres.
Le jour o? je comprends promis je rédige un paragraphe pour le wiki l? dessus  :)

alekmaul

Déja, le dernier param?tre de dmaCopyCGram, c'est la taille , donc pas de OBJ_SIZE16 mais le nombre de couleur 16*2 certainement pour toi (1 couleur est codée sur 16 bits).
Ensuite, ton probl?me doit venir des omSet qui ne doivent pas contenir les bons param?tres car ton init me semble OK l? ...
Enfin, reprend la derni?re verison de pvsneslib de googlecode, je crois me souvenir que j'avais un bug sur les sprites.
En dernier recours, poste tout ton code et tes bitmaps, j'essayerais de compiler tout cela de mon coté et voir d'o? vient le probl?me.

ccc

Merci AlekMaul,
Tu as raison pour les dmaCopyCGram je ne sais pas pourquoi je suis allé coller OBJ_SIZE16 dedans...
Dans 16*2 le 2 c'est pour 2 octets c'est ça (16 sprites fois 16 bits) ?
Ok je me réponds moi m?me  :
\param size the size in bytes of the data to copy. 

Je vais rechecker mes oamset maintenant  ;)

Pour la nouvelle version de la lib il y a un param?tre de plus dans l'appel de la fonction oamInitGfxSet (la taille des palettes justement).  Par contre j'imagine que du tout les programmes écrits pour une version ne sont pas comptibles avec l'autre :-( Du coup si cette derni?re version fonctionne faudra mettre ? jour le wiki et la doc.

PS : sur le wiki il y a un rigolo qui a collé un lien sur la page d'accueil dans "Other" sur un truc ? Singapour...

alekmaul

Merci pour le probl?me sur le wiki, c'est corrigé. Je passerais ? la version suivante de dokuwiki pour arr?ter ces co...
Pour la mise ? jour, oui, je reprends dés que je peux, je suis en ce moment hélas sur un autre projet qui me prend 100% de mon temps (novuelle console sous opendingux).
Essayes de me donner tout le code source, je verrais o? ça cloche, mais je pencherais pour un oamSet pas fait ou alors trop loin d'un VBlank.

ccc

#10
J'ai collé le fichier zip contenant le projet ? cette adresse

J'ai nettoyé le code pour ne laisser que l'affichage des sprites, malheureusement je s?che toujours :-(
Si j'utilise 3 oamInitGfxSet ça me donne ça sous, dans l'ordre, zsnes, no$snes et bsnes :

Je précise que le premier sprite (monstre vert) les 9 images sont situées de 0 ? 14+32, le deuxi?me (ours) commence en 64..78 et 96, et le troisi?me (boulette) s'étend de 128 ? 142 plus le 160 en bonus. J'avais pensé qu'ils se mettraient les uns ? la suite des autres (comprendre que le sprite de l'ours aurait du commencer en 32+2 soit 34) mais apparemment non  :-\
En gardant les m?mes offset pour les sprites et en changeant les 2 derniers oamInitGfxSet par les dmaCopyVram/dmaCopyCGram comme tu me l'as indiqué j'obtiens ceci :

Je n'ai que les sprites initialisés par l'oamInitGfxSet qui s'affichent  :(

Remarques :
-sous bsnes j'ai une couleur de fond, pas toujours la m?me, qui s'affiche alors que j'ai fait un disable des background...Et ça avec les deux techniques oam ou dma.
-toujours sous bsnes avec la méthode du triple oam j'ai les sprites d'offset 0, 64 et 128 qui ne s'affichent pas (cf la premi?re ligne est manquante) alors qu'ils sont bien l? avec les 2 autres émus
-bsnes, toujours, est le seul ? m'afficher quelque chose pour les lignes des sprites ours et boulette, m'enfin ça ressemble ? rien.

Merci d'avance pour ton aide !

alekmaul

Hello, je regarde dés que je peux.
Je te tiens au courant.

ccc

Up !
Si tu pouvais trouver une minute ou deux pour mon probl?me je t'en serais infiniment reconnaissant  8)
Il n'y a pas de caract?re d'urgence ceci-dit, loin de moi l'idée de te vouloir te mettre la pression :-[ !

alekmaul

erf, tu as raison de relancer mais je dois dire qu'en ce moment c'est aps simple.
Ton archive est sur le bureau de mon PC? je l'a vois tous les matins. je m'en occupe dés que possible ....
Désolé de ne pas ?tre plus rapide,  :-[ :-X

alekmaul

Bon, j'ai regardé et trouvé ton probl?me.
C'est l'adresse de la mémoire qui était pas bonne (faut divisé par 2 et surtout prendre la taille et non l'adresse de tes graphiques) , voici la bonne implémentation :

Citation
dmaCopyVram(&gfxpours, adrenvramcopie/2+(&gfxpsrite_end-&gfxpsrite)/2,(&gfxpours_end-&gfxpours));
dmaCopyVram(&gfxpboulette, adrenvramcopie/2+(&gfxpsrite_end-&gfxpsrite)/2+(&gfxpours_end-&gfxpours)/2,(&gfxpboulette_end-&gfxpboulette));

Et ainsi , tes sprites sont représentés ? l'écran, comme ci dessous (faut ?tre connecté pour voir le bitmap).