JieF
16/09/2007, 11h43
Bonjour, premier post donc de l'indulgence s'il vous plait :)
Voilà, je commence tout juste en dev NDS, d'ailleurs j'ai même pas de NDS, bref. Gêné par les problèmes de fragmentation de mémoires pour les sprites avec la palib, je me suis dis que je pourrai regarder du coté de la ndslib.
J'ai donc créé une fonction createsprite à l'instar de la palib en pensant ecraser la même zone mémoire à chaque fois. Si SPRITE_GFX_SUB pointe en mémoire et que j'incrémente pour y copier mes données alors c'est toujours la même zone que j'utilise non ? mais apparemment c'est pas aussi simple.
Donc cette fonction je l'utilise dans une démo de bourrin qui recrée une trentaine de sprites à chaque touch du stylet dans un zone de l'écran.
Résultat : No$gba plante au bout d'une grosse cinquantaine de clicks mais me dit dans utility-->errors -->
Errors per second -- 0
Total Errors -- 0
Low Power Mode -- Okay
Multiboot Support -- Unsupported (bad entrypoint)
Quality Rating -- Good (better than most GBA games)
et quant à DeSmuME : il fait tourner mon test sans planter du tout.
Dans la pratique, après avoir refilé le .nds à un pote qui a tout ce qu'il faut, il y a des p'tits bugs d'affichages sur les sprites et ça plante au bout de 2 ou 3 clicks. Le binaire se trouve ici : http://asso-claj.ovh.org/Sprite.nds et la source ici : http://asso-claj.ovh.org/Sprite.cpp.
vu la taille de la source, je la recopie ici :
#include <stdlib.h>
#include <nds.h>
#include <stdio.h>
#include <nds/arm9/image.h>
//include our ball pcx file (auto generated)
#include "ball_pcx.h"
#include "ball_old_pcx.h"
#include "f1_pcx.h"
#include "f2_pcx.h"
#define NUM_SPRITES 128
const u8 *tab_file[] = {ball_pcx,ball_old_pcx,f1_pcx,f2_pcx,};
SpriteEntry OAMCopySub[128];
touchPosition Stylus;
// Function: Detect button
int stylusInBox(int x,int y,int w,int h){
if(keysHeld() && KEY_TOUCH && Stylus.px>=x && Stylus.py>=y && Stylus.px<=(x+w) && Stylus.py<=(y+h)){
return 1;
}else{
return 0;
}
}
//simple sprite struct
typedef struct {
int x,y; //location
int dx, dy; //speed
SpriteEntry* oam;
int gfxID; //graphics location
int ID; //graphics ID
}Sprite;
//init sprites
Sprite sprites[NUM_SPRITES];
//---------------------------------------------------------------------------------
void initOAM(void) {
//---------------------------------------------------------------------------------
int i;
for(i = 0; i < 128; i++) {
OAMCopySub[i].attribute[0] = ATTR0_DISABLED;
}
}
//---------------------------------------------------------------------------------
void updateOAM(void) {
//---------------------------------------------------------------------------------
unsigned int i;
for(i = 0; i < 128 * sizeof(SpriteEntry) / 4 ; i++)
{
((uint32*)OAM_SUB)[i] = ((uint32*)OAMCopySub)[i];
}
}
//---------------------------------------------------------------------------------
void CreateSprite(u8 *file_pcx,int i,int x,int y){
//---------------------------------------------------------------------------------
sImage file;
//load our ball pcx file into an image
loadPCX((u8*)file_pcx, &file);
//tile it so it is usefull as sprite data
imageTileData(&file);
// Palette initialisation
for(int i = 0; i < 256; i++){
SPRITE_PALETTE_SUB[i*256] = file.palette[i];
}
// Sprite initialisation
for(int j = 0; j< 32*16; j++){
SPRITE_GFX_SUB[j+(i*1024)] = file.image.data16[j];
}
sprites[i].gfxID = i*64;
sprites[i].oam = &OAMCopySub[i];
sprites[i].ID = i;
//set up our sprites OAM entry attributes
sprites[i].oam->attribute[0] = ATTR0_COLOR_256 | ATTR0_SQUARE;
sprites[i].oam->attribute[1] = ATTR1_SIZE_32;
sprites[i].oam->attribute[2] = sprites[i].gfxID;
sprites[i].oam->attribute[1] |= (x & 0x01FF);
sprites[i].oam->attribute[0] |= (y & 0x00FF);
}
//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------
//turn on the power to the system
powerON(POWER_ALL);
//One palette for_all
paletteForAll((u8*)tab_file[0]);
//initOAM();
//set main display to render directly from the frame buffer
videoSetMode(0);
//set up the sub display
videoSetModeSub(MODE_0_2D |
DISPLAY_SPR_1D_LAYOUT |
DISPLAY_SPR_ACTIVE |
DISPLAY_BG0_ACTIVE |
DISPLAY_BG1_ACTIVE );
//vram banks are somewhat complex
vramSetMainBanks(VRAM_A_LCD, VRAM_B_LCD, VRAM_C_SUB_BG, VRAM_D_SUB_SPRITE);
// a vblank interrupt is needed to use swiWaitForVBlank()
// since the dispatcher handles the flags no handler is required
irqInit();
irqSet(IRQ_VBLANK, 0);
while (1){
scanKeys();
Stylus=touchReadXY();
if(stylusInBox(0,0,255/2,190)){
CreateSprite((u8*)tab_file[0],0,0,0);
CreateSprite((u8*)tab_file[1],1,32,0);
CreateSprite((u8*)tab_file[2],2,64,0);
CreateSprite((u8*)tab_file[3],3,96,0);
CreateSprite((u8*)tab_file[0],4,128,0);
CreateSprite((u8*)tab_file[1],5,160,0);
CreateSprite((u8*)tab_file[2],6,192,0);
CreateSprite((u8*)tab_file[3],7,224,0);
CreateSprite((u8*)tab_file[0],8,0,32);
CreateSprite((u8*)tab_file[1],9,32,32);
CreateSprite((u8*)tab_file[2],10,64,32);
CreateSprite((u8*)tab_file[3],11,96,32);
CreateSprite((u8*)tab_file[0],12,128,32);
CreateSprite((u8*)tab_file[1],13,160,32);
CreateSprite((u8*)tab_file[2],14,192,32);
CreateSprite((u8*)tab_file[3],15,224,32);
CreateSprite((u8*)tab_file[0],16,0,64);
CreateSprite((u8*)tab_file[1],17,32,64);
CreateSprite((u8*)tab_file[2],18,64,64);
CreateSprite((u8*)tab_file[3],19,96,64);
CreateSprite((u8*)tab_file[0],20,128,64);
CreateSprite((u8*)tab_file[1],21,160,64);
CreateSprite((u8*)tab_file[2],22,192,64);
CreateSprite((u8*)tab_file[3],23,224,64);
CreateSprite((u8*)tab_file[0],24,0,96);
CreateSprite((u8*)tab_file[1],25,32,96);
CreateSprite((u8*)tab_file[2],26,64,96);
CreateSprite((u8*)tab_file[3],27,96,96);
CreateSprite((u8*)tab_file[0],28,128,96);
CreateSprite((u8*)tab_file[1],29,160,96);
CreateSprite((u8*)tab_file[2],30,192,96);
CreateSprite((u8*)tab_file[3],31,224,96);
}
if(stylusInBox(255/2,0,255/2,190)){
CreateSprite((u8*)tab_file[1],0,0,0);
CreateSprite((u8*)tab_file[2],1,32,0);
CreateSprite((u8*)tab_file[3],2,64,0);
CreateSprite((u8*)tab_file[0],3,96,0);
CreateSprite((u8*)tab_file[1],4,128,0);
CreateSprite((u8*)tab_file[2],5,160,0);
CreateSprite((u8*)tab_file[3],6,192,0);
CreateSprite((u8*)tab_file[0],7,224,0);
CreateSprite((u8*)tab_file[1],8,0,32);
CreateSprite((u8*)tab_file[2],9,32,32);
CreateSprite((u8*)tab_file[3],10,64,32);
CreateSprite((u8*)tab_file[0],11,96,32);
CreateSprite((u8*)tab_file[1],12,128,32);
CreateSprite((u8*)tab_file[2],13,160,32);
CreateSprite((u8*)tab_file[3],14,192,32);
CreateSprite((u8*)tab_file[0],15,224,32);
CreateSprite((u8*)tab_file[1],16,0,64);
CreateSprite((u8*)tab_file[2],17,32,64);
CreateSprite((u8*)tab_file[3],18,64,64);
CreateSprite((u8*)tab_file[0],19,96,64);
CreateSprite((u8*)tab_file[1],20,128,64);
CreateSprite((u8*)tab_file[2],21,160,64);
CreateSprite((u8*)tab_file[3],22,192,64);
CreateSprite((u8*)tab_file[0],23,224,64);
CreateSprite((u8*)tab_file[1],24,0,96);
CreateSprite((u8*)tab_file[2],25,32,96);
CreateSprite((u8*)tab_file[3],26,64,96);
CreateSprite((u8*)tab_file[0],27,96,96);
CreateSprite((u8*)tab_file[1],28,128,96);
CreateSprite((u8*)tab_file[2],29,160,96);
CreateSprite((u8*)tab_file[3],30,192,96);
CreateSprite((u8*)tab_file[0],31,224,96);
}
swiWaitForVBlank();
updateOAM();
}
}
Quelqu'un qui s'y connait pourrait-il m'apporter de l'aide, me filer une piste ???
- J'ai tenté de charger la palette à part pour tous les sprites genre dans une fonction palette4all(), mais ça ne marche pas (un léger mieux peut-être, mais c une seule palette*NUM_SPRITES pour tous les sprites)
- j'ai essayé d'utiliser un autre registre que SUB mais ça ne m'affiche plus les sprites.
Voilà, je commence tout juste en dev NDS, d'ailleurs j'ai même pas de NDS, bref. Gêné par les problèmes de fragmentation de mémoires pour les sprites avec la palib, je me suis dis que je pourrai regarder du coté de la ndslib.
J'ai donc créé une fonction createsprite à l'instar de la palib en pensant ecraser la même zone mémoire à chaque fois. Si SPRITE_GFX_SUB pointe en mémoire et que j'incrémente pour y copier mes données alors c'est toujours la même zone que j'utilise non ? mais apparemment c'est pas aussi simple.
Donc cette fonction je l'utilise dans une démo de bourrin qui recrée une trentaine de sprites à chaque touch du stylet dans un zone de l'écran.
Résultat : No$gba plante au bout d'une grosse cinquantaine de clicks mais me dit dans utility-->errors -->
Errors per second -- 0
Total Errors -- 0
Low Power Mode -- Okay
Multiboot Support -- Unsupported (bad entrypoint)
Quality Rating -- Good (better than most GBA games)
et quant à DeSmuME : il fait tourner mon test sans planter du tout.
Dans la pratique, après avoir refilé le .nds à un pote qui a tout ce qu'il faut, il y a des p'tits bugs d'affichages sur les sprites et ça plante au bout de 2 ou 3 clicks. Le binaire se trouve ici : http://asso-claj.ovh.org/Sprite.nds et la source ici : http://asso-claj.ovh.org/Sprite.cpp.
vu la taille de la source, je la recopie ici :
#include <stdlib.h>
#include <nds.h>
#include <stdio.h>
#include <nds/arm9/image.h>
//include our ball pcx file (auto generated)
#include "ball_pcx.h"
#include "ball_old_pcx.h"
#include "f1_pcx.h"
#include "f2_pcx.h"
#define NUM_SPRITES 128
const u8 *tab_file[] = {ball_pcx,ball_old_pcx,f1_pcx,f2_pcx,};
SpriteEntry OAMCopySub[128];
touchPosition Stylus;
// Function: Detect button
int stylusInBox(int x,int y,int w,int h){
if(keysHeld() && KEY_TOUCH && Stylus.px>=x && Stylus.py>=y && Stylus.px<=(x+w) && Stylus.py<=(y+h)){
return 1;
}else{
return 0;
}
}
//simple sprite struct
typedef struct {
int x,y; //location
int dx, dy; //speed
SpriteEntry* oam;
int gfxID; //graphics location
int ID; //graphics ID
}Sprite;
//init sprites
Sprite sprites[NUM_SPRITES];
//---------------------------------------------------------------------------------
void initOAM(void) {
//---------------------------------------------------------------------------------
int i;
for(i = 0; i < 128; i++) {
OAMCopySub[i].attribute[0] = ATTR0_DISABLED;
}
}
//---------------------------------------------------------------------------------
void updateOAM(void) {
//---------------------------------------------------------------------------------
unsigned int i;
for(i = 0; i < 128 * sizeof(SpriteEntry) / 4 ; i++)
{
((uint32*)OAM_SUB)[i] = ((uint32*)OAMCopySub)[i];
}
}
//---------------------------------------------------------------------------------
void CreateSprite(u8 *file_pcx,int i,int x,int y){
//---------------------------------------------------------------------------------
sImage file;
//load our ball pcx file into an image
loadPCX((u8*)file_pcx, &file);
//tile it so it is usefull as sprite data
imageTileData(&file);
// Palette initialisation
for(int i = 0; i < 256; i++){
SPRITE_PALETTE_SUB[i*256] = file.palette[i];
}
// Sprite initialisation
for(int j = 0; j< 32*16; j++){
SPRITE_GFX_SUB[j+(i*1024)] = file.image.data16[j];
}
sprites[i].gfxID = i*64;
sprites[i].oam = &OAMCopySub[i];
sprites[i].ID = i;
//set up our sprites OAM entry attributes
sprites[i].oam->attribute[0] = ATTR0_COLOR_256 | ATTR0_SQUARE;
sprites[i].oam->attribute[1] = ATTR1_SIZE_32;
sprites[i].oam->attribute[2] = sprites[i].gfxID;
sprites[i].oam->attribute[1] |= (x & 0x01FF);
sprites[i].oam->attribute[0] |= (y & 0x00FF);
}
//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------
//turn on the power to the system
powerON(POWER_ALL);
//One palette for_all
paletteForAll((u8*)tab_file[0]);
//initOAM();
//set main display to render directly from the frame buffer
videoSetMode(0);
//set up the sub display
videoSetModeSub(MODE_0_2D |
DISPLAY_SPR_1D_LAYOUT |
DISPLAY_SPR_ACTIVE |
DISPLAY_BG0_ACTIVE |
DISPLAY_BG1_ACTIVE );
//vram banks are somewhat complex
vramSetMainBanks(VRAM_A_LCD, VRAM_B_LCD, VRAM_C_SUB_BG, VRAM_D_SUB_SPRITE);
// a vblank interrupt is needed to use swiWaitForVBlank()
// since the dispatcher handles the flags no handler is required
irqInit();
irqSet(IRQ_VBLANK, 0);
while (1){
scanKeys();
Stylus=touchReadXY();
if(stylusInBox(0,0,255/2,190)){
CreateSprite((u8*)tab_file[0],0,0,0);
CreateSprite((u8*)tab_file[1],1,32,0);
CreateSprite((u8*)tab_file[2],2,64,0);
CreateSprite((u8*)tab_file[3],3,96,0);
CreateSprite((u8*)tab_file[0],4,128,0);
CreateSprite((u8*)tab_file[1],5,160,0);
CreateSprite((u8*)tab_file[2],6,192,0);
CreateSprite((u8*)tab_file[3],7,224,0);
CreateSprite((u8*)tab_file[0],8,0,32);
CreateSprite((u8*)tab_file[1],9,32,32);
CreateSprite((u8*)tab_file[2],10,64,32);
CreateSprite((u8*)tab_file[3],11,96,32);
CreateSprite((u8*)tab_file[0],12,128,32);
CreateSprite((u8*)tab_file[1],13,160,32);
CreateSprite((u8*)tab_file[2],14,192,32);
CreateSprite((u8*)tab_file[3],15,224,32);
CreateSprite((u8*)tab_file[0],16,0,64);
CreateSprite((u8*)tab_file[1],17,32,64);
CreateSprite((u8*)tab_file[2],18,64,64);
CreateSprite((u8*)tab_file[3],19,96,64);
CreateSprite((u8*)tab_file[0],20,128,64);
CreateSprite((u8*)tab_file[1],21,160,64);
CreateSprite((u8*)tab_file[2],22,192,64);
CreateSprite((u8*)tab_file[3],23,224,64);
CreateSprite((u8*)tab_file[0],24,0,96);
CreateSprite((u8*)tab_file[1],25,32,96);
CreateSprite((u8*)tab_file[2],26,64,96);
CreateSprite((u8*)tab_file[3],27,96,96);
CreateSprite((u8*)tab_file[0],28,128,96);
CreateSprite((u8*)tab_file[1],29,160,96);
CreateSprite((u8*)tab_file[2],30,192,96);
CreateSprite((u8*)tab_file[3],31,224,96);
}
if(stylusInBox(255/2,0,255/2,190)){
CreateSprite((u8*)tab_file[1],0,0,0);
CreateSprite((u8*)tab_file[2],1,32,0);
CreateSprite((u8*)tab_file[3],2,64,0);
CreateSprite((u8*)tab_file[0],3,96,0);
CreateSprite((u8*)tab_file[1],4,128,0);
CreateSprite((u8*)tab_file[2],5,160,0);
CreateSprite((u8*)tab_file[3],6,192,0);
CreateSprite((u8*)tab_file[0],7,224,0);
CreateSprite((u8*)tab_file[1],8,0,32);
CreateSprite((u8*)tab_file[2],9,32,32);
CreateSprite((u8*)tab_file[3],10,64,32);
CreateSprite((u8*)tab_file[0],11,96,32);
CreateSprite((u8*)tab_file[1],12,128,32);
CreateSprite((u8*)tab_file[2],13,160,32);
CreateSprite((u8*)tab_file[3],14,192,32);
CreateSprite((u8*)tab_file[0],15,224,32);
CreateSprite((u8*)tab_file[1],16,0,64);
CreateSprite((u8*)tab_file[2],17,32,64);
CreateSprite((u8*)tab_file[3],18,64,64);
CreateSprite((u8*)tab_file[0],19,96,64);
CreateSprite((u8*)tab_file[1],20,128,64);
CreateSprite((u8*)tab_file[2],21,160,64);
CreateSprite((u8*)tab_file[3],22,192,64);
CreateSprite((u8*)tab_file[0],23,224,64);
CreateSprite((u8*)tab_file[1],24,0,96);
CreateSprite((u8*)tab_file[2],25,32,96);
CreateSprite((u8*)tab_file[3],26,64,96);
CreateSprite((u8*)tab_file[0],27,96,96);
CreateSprite((u8*)tab_file[1],28,128,96);
CreateSprite((u8*)tab_file[2],29,160,96);
CreateSprite((u8*)tab_file[3],30,192,96);
CreateSprite((u8*)tab_file[0],31,224,96);
}
swiWaitForVBlank();
updateOAM();
}
}
Quelqu'un qui s'y connait pourrait-il m'apporter de l'aide, me filer une piste ???
- J'ai tenté de charger la palette à part pour tous les sprites genre dans une fonction palette4all(), mais ça ne marche pas (un léger mieux peut-être, mais c une seule palette*NUM_SPRITES pour tous les sprites)
- j'ai essayé d'utiliser un autre registre que SUB mais ça ne m'affiche plus les sprites.