gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Messed up sprite? bin file

#138591 - ubercatch22 - Sun Aug 26, 2007 5:08 am

when i excute my .nds file it work but my sprite are horribly dissorted

heres a urlto the image of it

http://i183.photobucket.com/albums/x51/Ubercatch/disportspitesds.jpg

can any one help? oh heres the code as well(code was taken from a example from the 2055 dev kit because of the bin type file since i cant get
my .pcx images to work)

i use adobe photoshop cs3 extended for the .pcx but i get the error that the compiler cant find the file even know it is there.

[code

#include <stdlib.h>
#include <nds.h>

// these files are generated automatically by the bin2o rule
#include "palette_bin.h"
#include "man_bin.h"

#define NUM_SPRITES 128

SpriteEntry OAMCopySub[128];


//simple sprite struct
typedef struct {
int x,y; //location
int dx, dy; //speed
SpriteEntry* oam;
int gfxID; //graphics lovation
}Sprite;


//---------------------------------------------------------------------------------
void MoveSprite(Sprite* sp) {
//---------------------------------------------------------------------------------
int x = sp->x >> 8;
int y = sp->y >> 8;

sp->oam->attribute[1] &= 0xFE00;
sp->oam->attribute[1] |= (x & 0x01FF);

sp->oam->attribute[0] &= 0xFF00;
sp->oam->attribute[0] |= (y & 0x00FF);

}



//---------------------------------------------------------------------------------
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++)
{
((uint16*)OAM_SUB)[i] = ((uint16*)OAMCopySub)[i];
}
}


//---------------------------------------------------------------------------------
void irqVBlank(void) {
//---------------------------------------------------------------------------------
}

//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------

uint16* back = VRAM_A;
uint16* front = VRAM_B;

Sprite sprites[NUM_SPRITES];

int i, delta = 0;
int ix = 0;
int iy = 0;
int screen = 1;
uint16* map0 = (uint16*)SCREEN_BASE_BLOCK_SUB(1);
uint16* map1 = (uint16*)SCREEN_BASE_BLOCK_SUB(2);
uint16 red;

//turn on the power to the system
powerON(POWER_ALL);

//set main display to render directly from the frame buffer
videoSetMode(MODE_FB1);

//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, irqVBlank);

// Sprite initialisation
for(i = 0; i < 256; i++)
SPRITE_PALETTE_SUB[i] = ((u16*)palette_bin)[i];

for(i = 0; i< 32*16; i++)
SPRITE_GFX_SUB[i] = ((u16*)man_bin)[i];

//turn off sprites
initOAM();

for(i = 0; i < NUM_SPRITES; i++) {
//random place and speed
sprites[i].x = rand() & 0xFFFF;
sprites[i].y = rand() & 0x7FFF;
sprites[i].dx = (rand() & 0xFF) + 0x100;
sprites[i].dy = (rand() & 0xFF) + 0x100;

if(rand() & 1)
sprites[i].dx = -sprites[i].dx;
if(rand() & 1)
sprites[i].dy = -sprites[i].dy;

sprites[i].oam = &OAMCopySub[i];
sprites[i].gfxID = 0;

//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;
}

//set up two backgrounds to scroll around
SUB_BG0_CR = BG_COLOR_256 | (1 << SCREEN_SHIFT);
SUB_BG1_CR = BG_COLOR_256 | (2 << SCREEN_SHIFT);

BG_PALETTE_SUB[0] = RGB15(10,10,10);
BG_PALETTE_SUB[1] = RGB15(0,16,0);
BG_PALETTE_SUB[2] = RGB15(0,0,31);

//load the maps with alternating tiles (0,1 for bg0 and 0,2 for bg1)
for(iy = 0; iy < 32; iy++)
for(ix = 0; ix <32; ix++) {
map0[iy * 32 + ix] = (ix ^ iy) & 1;
map1[iy * 32 + ix] = ((ix ^ iy) & 1)<<1;
}

//fill 2 tiles with different colors
for(i = 0; i < 64 / 2; i++) {
BG_GFX_SUB[i+32] = 0x0101;
BG_GFX_SUB[i+32+32] = 0x0202;
}

while (1) {
//scroll the background
SUB_BG0_X0 = delta ;
SUB_BG0_Y0 = delta++ ;

//move the sprites
for(i = 0; i < NUM_SPRITES; i++) {
sprites[i].x += sprites[i].dx;
sprites[i].y += sprites[i].dy;

//check for collision with the screen boundries
if(sprites[i].x < (1<<8) || sprites[i].x > (247 << 8))
sprites[i].dx = -sprites[i].dx;

if(sprites[i].y < (1<<8) || sprites[i].y > (182 << 8))
sprites[i].dy = -sprites[i].dy;

//reposition the sprites
MoveSprite(&sprites[i]);
}



//do the plasma/fire
for(ix = 0; ix < SCREEN_WIDTH; ix++) {
back[ix + SCREEN_WIDTH * (SCREEN_HEIGHT - 1)] = rand()& 0xFFFF;
back[ix + SCREEN_WIDTH * (SCREEN_HEIGHT - 2)] = rand()& 0xFFFF;
}

back++;

for(iy = 1; iy < SCREEN_HEIGHT - 2 ; iy++) {
for(ix = 1; ix < SCREEN_WIDTH - 1; ix++) {
red = 0;

red += front[0];
red += front[2];

front += SCREEN_WIDTH;

red += front[0];
red += front[1];
red += front[2];

front += SCREEN_WIDTH;

red += front[0];
red += front[1];
red += front[2];

front -= (2 * SCREEN_WIDTH) - 1;

back[0] = (red >> 3);
back++;
}
back += 2;
front += 2;

}

swiWaitForVBlank();

updateOAM();

//flip screens
if(screen) {
videoSetMode(MODE_FB1);
front = VRAM_B;
back = VRAM_A;
screen = 0;
}
else
{
videoSetMode(MODE_FB0);
front = VRAM_A;
back = VRAM_B;
screen = 1;
}

}
return 0;

}

[/code]
[/img][url][/url]

#138593 - SaruCoder - Sun Aug 26, 2007 6:17 am

It looks like the sprite raster data isn't mapped properly. Sprite gfx data is divided into 8x8 pixel tiles. So, popping in a raster image directly won't display properly.

I recommend you try using wingrit after you create your pcx or bmp. It'll remap your sprite gfx data into the correct order, and load it into a (u8/u16/u32) array in a .c file. I find those are easier to use then converting pcx or bmps to a bin file.
http://www.coranac.com/projects.php#grit

#138594 - ubercatch22 - Sun Aug 26, 2007 6:25 am

SaruCoder wrote:
It looks like the sprite raster data isn't mapped properly. Sprite gfx data is divided into 8x8 pixel tiles. So, popping in a raster image directly won't display properly.

I recommend you try using wingrit after you create your pcx or bmp. It'll remap your sprite gfx data into the correct order, and load it into a (u8/u16/u32) array in a .c file. I find those are easier to use then converting pcx or bmps to a bin file.
http://www.coranac.com/projects.php#grit


can you explain the sprite raster a little more. i seems that u16 is best for the sprite where it is still disprted but not the worst

#138595 - SaruCoder - Sun Aug 26, 2007 8:29 am

You know how in some countries, text is read left to right, and in some places it's read top to bottom (starting at the back of the book too)?

It's the same principles here, the nds/gba reads in a image differently.

The image raster for PCX and BMPs are read left to right, then top to bottom. Like how a TV works. It starts at the top-left, and reads side to side.

NDS/GBA however breaks down a image into 8x8 pixel tiles, and then treats each block as an raster image.

For example, if you have a 64x64 BMP raster image, the NDS/GBA will read the first 64 pixels (#of pixels in a 8x8 tile). Then it'll think it's the first tile and it'll render a 8x8 tile of gobbledegoop instead of rendering it as the top line of your BMP.

So that's the "technical" details in a nutshell. But you don't need to worry about that when you use wingrit, but it's good to know.

And yes, stick to u16 because that's how SPRITE_GFX(_SUB) are aligned.

#138598 - LiraNuna - Sun Aug 26, 2007 10:41 am

what are copying into VRAM is probably a raw PCX file.
Quote:
i use adobe photoshop cs3 extended for the .pcx but i get the error that the compiler cant find the file even know it is there.

This is because there is no rule for the bin2o macro (I bet the compiler errors something along the line of "no rule to make target filename.pcx.o")
What you should do, is to convert the PCX file into a data asset the DS GPU can work with. As SaruCoder said, a sprite is made out of 8x8 tiles linearly (also called 1D mode), of course this can be changed, but other modes are rarely used.

To convert sprites, I recommend using gfx2gba using the command
Code:
gfx2gba -c256 -t8 image.pcx

-c256 is 256 color output, (I saw you were using ATTR0_COLOR_256)
-t8 means square tiles of 8x8.

you will get two files as output - image.raw and image.pal. rename them to .bin and include them in the 'data' folder. [/code]
_________________
Private property.
Violators will be shot, survivors will be shot again.