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 > My nds works fine on DeSmuMe, but not on my actual DS >&a

#153232 - TheMagnitude - Wed Mar 26, 2008 8:18 pm

This is part of a tutorial on patater, but i changed the function initsprites() to my own function to initialize a single sprite, to save me copying and pasting lots of code when i progress with more sprites.

It works fine on DeSmuMe, the orange shuttle moves horizontally across the screen and the moon moves vertically.

But when i pop it onto my real ds the sprites turn out black, but still transparrent, and they move, except the moon sprite appears to have an posX of 0, when i set it to 150.

Its the addObject() function that seems to be the problem, since that is the only thing I have changed from the original source in the tutorial.

Code:
/*
 *  main.cpp
 * 
 *  Created by Jaeden Amero on 11/12/07.
 *  Copyright 2007. All rights reserved.
 *
 */

#include <nds.h>
#include <assert.h>
#include "sprites.h"

/* Backgrounds */
#include "starField.h"
#include "planet.h"
#include "splash.h"
/* Sprites */
#include "orangeShuttle.h"
#include "moon.h"

// SPRITE GLOBALS
SpriteInfo spriteInfo[SPRITE_COUNT];
tOAM *oam;

static const int BYTES_PER_16_COLOR_TILE = 32;
static const int COLORS_PER_PALETTE = 16;
static const int BOUNDARY_VALUE = 32;
static const int OFFSET_MULTIPLIER = BOUNDARY_VALUE / sizeof(SPRITE_GFX[0]);
int nextAvailableTileIdx = 0;
static int oamIdIterator = 0;

/* Select a low priority DMA channel to perform our background copying. */
static const int DMA_CHANNEL = 3;

void initVideo() {
    /*
     *  Map VRAM to display a background on the main and sub screens.
     *
     *  The vramSetMainBanks function takes four arguments, one for each of the
     *  major VRAM banks. We can use it as shorthand for assigning values to
     *  each of the VRAM bank's control registers.
     *
     *  We map banks A and B to main screen  background memory. This gives us
     *  256KB, which is a healthy amount for 16-bit graphics.
     *
     *  We map bank C to sub screen background memory.
     *
     *  We map bank D to LCD. This setting is generally used for when we aren't
     *  using a particular bank.
     *
     *  We map bank E to main screen sprite memory (aka object memory).
     */
    vramSetMainBanks(VRAM_A_MAIN_BG_0x06000000,
                     VRAM_B_MAIN_BG_0x06020000,
                     VRAM_C_SUB_BG_0x06200000,
                     VRAM_D_LCD);

    vramSetBankE(VRAM_E_MAIN_SPRITE);

    /*  Set the video mode on the main screen. */
    videoSetMode(MODE_5_2D | // Set the graphics mode to Mode 5
                 DISPLAY_BG2_ACTIVE | // Enable BG2 for display
                 DISPLAY_BG3_ACTIVE | // Enable BG3 for display
                 DISPLAY_SPR_ACTIVE | // Enable sprites for display
                 DISPLAY_SPR_1D       // Enable 1D tiled sprites
                 );

    /*  Set the video mode on the sub screen. */
    videoSetModeSub(MODE_5_2D | // Set the graphics mode to Mode 5
                    DISPLAY_BG3_ACTIVE); // Enable BG3 for display
}

void initBackgrounds() {
    /*  Set up affine background 3 on main as a 16-bit color background */
    BG3_CR = BG_BMP16_256x256 |
             BG_BMP_BASE(0) | // The starting place in memory
             BG_PRIORITY(3); // A low priority

    /*  Set the affine transformation matrix for the main screen background 3
     *  to be the identity matrix.
     */
    BG3_XDX = 1 << 8;
    BG3_XDY = 0;
    BG3_YDX = 0;
    BG3_YDY = 1 << 8;

    /*  Place main screen background 3 at the origin (upper left of the screen)
     */
    BG3_CX = 0;
    BG3_CY = 0;

    /*  Set up affine background 2 on main as a 16-bit color background */
    BG2_CR = BG_BMP16_128x128 |
             BG_BMP_BASE(8) | // The starting place in memory
             BG_PRIORITY(2);  // A higher priority

    /*  Set the affine transformation matrix for the main screen background 3
     *  to be the identity matrix.
     */
    BG2_XDX = 1 << 8;
    BG2_XDY = 0;
    BG2_YDX = 0;
    BG2_YDY = 1 << 8;

    /*  Place main screen background 2 an interesting place. */
    BG2_CX = -(SCREEN_WIDTH / 2 - 32) << 8;
    BG2_CY = -32 << 8;

    /*  Set up affine background 3 on the sub screen as a 16-bit color
     *  background
     */
    SUB_BG3_CR = BG_BMP16_256x256 |
                 BG_BMP_BASE(0) | // The starting place in memory
                 BG_PRIORITY(3); // A low priority

    /*  Set the affine transformation matrix for the sub screen background 3
     *  to be the identity matrix.
     */
    SUB_BG3_XDX = 1 << 8;
    SUB_BG3_XDY = 0;
    SUB_BG3_YDX = 0;
    SUB_BG3_YDY = 1 << 8;

    /*
     *  Place main screen background 3 at the origin (upper left of the screen)
     */
    SUB_BG3_CX = 0;
    SUB_BG3_CY = 0;
}

SpriteEntry * addObject(
   const unsigned short pal[],
   const unsigned int tiles[],
   uint32 palLen,
   uint32 tilesLen,
   u16 xpos, u16 ypos,
   int width, int height,
   int angle,
   bool affine,
   tObjColMode colmode,
   tObjMode objmode = OBJMODE_NORMAL,
   tObjPriority objpriority = OBJPRIORITY_0,
   bool hflip = false,
   bool vflip = false)
{
    assert(oamIdIterator < SPRITE_COUNT);
    SpriteInfo * info = &spriteInfo[oamIdIterator];
    SpriteEntry * obj = &oam->spriteBuffer[oamIdIterator];
   assert((height==64 || height==32 || height==16 || height==8) && (width==64 || width==32 || width==16 || width==8));
   // INFO
   info->oamId = oamIdIterator;
   info->width = width;
    info->height = height;
    info->angle = angle;
    info->entry = obj;
   // ATTRIBUTE 0
   obj->posY = ypos;
   obj->isHidden = false;
   obj->isRotoscale = affine;
    assert(!obj->isRotoscale || (info->oamId < MATRIX_COUNT));
    obj->rsDouble = false;
    obj->objMode = objmode;
   obj->isMosaic = false;
    obj->colMode = colmode;
   if (height == width)
      obj->objShape = OBJSHAPE_SQUARE;
   else if (height>width)
      obj->objShape = OBJSHAPE_TALL;
   else if (height<width)
      obj->objShape = OBJSHAPE_WIDE;
   else
      obj->objShape = OBJSHAPE_FORBIDDEN;
   // ATTRIBUTE 1
   obj->posX = xpos;
   if (affine == true)
      obj->rsMatrixIdx = info->oamId;
   else
   {
      obj->hFlip = hflip;
      obj->vFlip = vflip;
   }
   switch (height >= width ? height : width)
   {
      case 8:
         obj->objSize = OBJSIZE_8;
      break;
      case 16:
         obj->objSize = OBJSIZE_16;
      break;
      case 32:
         obj->objSize = OBJSIZE_32;
      break;
      case 64:
         obj->objSize = OBJSIZE_64;
      break;
   }
   // ATTRIBUTE 2
    obj->tileIdx = nextAvailableTileIdx;
    nextAvailableTileIdx += tilesLen / BYTES_PER_16_COLOR_TILE;
    obj->objPriority = objpriority;
    obj->objPal = info->oamId;
   // ROTATE
   if (affine==true)
      rotateSprite(&oam->matrixBuffer[info->oamId],info->angle);
    // COPY SPRITE PALLETTES
   dmaCopyHalfWords(SPRITE_DMA_CHANNEL,
                     pal,
                     &SPRITE_PALETTE[info->oamId * COLORS_PER_PALETTE],
                     palLen);
   // COPY SPRITE GRAPHICS
    dmaCopyHalfWords(SPRITE_DMA_CHANNEL,
                     tiles,
                     &SPRITE_GFX[obj->tileIdx * OFFSET_MULTIPLIER],
                     tilesLen);
   ++oamIdIterator;
   return obj;
}

void displayStarField() {
    dmaCopyHalfWords(DMA_CHANNEL,
                     starFieldBitmap, /* This variable is generated for us by
                                       * grit. */
                     (uint16 *)BG_BMP_RAM(0), /* Our address for main
                                               * background 3 */
                     starFieldBitmapLen);
}

void displayPlanet() {
    dmaCopyHalfWords(DMA_CHANNEL,
                     planetBitmap, /* This variable is generated for us by
                                    * grit. */
                     (uint16 *)BG_BMP_RAM(8), /* Our address for main
                                               * background 2 */
                     planetBitmapLen);
}

void displaySplash() {
    dmaCopyHalfWords(DMA_CHANNEL,
                     splashBitmap, /* This variable is generated for us by
                                    * grit. */
                     (uint16 *)BG_BMP_RAM_SUB(0), /* Our address for sub
                                                     background 3 */
                     splashBitmapLen);
}

int main() {
    /*  Turn on the 2D graphics core. */
    powerON(POWER_ALL_2D);

    /*
     *  Set up interrupts.
     *
     *  We don't really get into what these do exactly at this point in the
     *  manual, but we still need to do them for now.
     */
    irqInit();
    irqSet(IRQ_VBLANK, 0);

    /*
     *  Configure the VRAM and background control registers.
     *
     *  Place the main screen on the bottom physical screen. Then arrange the
     *  VRAM banks. Next, confiure the background control registers.
     */
    lcdMainOnBottom();
    initVideo();
    initBackgrounds();

    /* Set up a few sprites. */
   oam = new tOAM();
   initOAM(oam);
   //initSprites(oam,spriteInfo);
   addObject(  orangeShuttlePal,
            orangeShuttleTiles,
            (uint32)orangeShuttlePalLen,
            (uint32)orangeShuttleTilesLen,
            (u16)100, (u16)100,
            64, 64,
            462,
            true,
            OBJCOLOR_16,
            OBJMODE_NORMAL,
            OBJPRIORITY_0,
            false,
            false);
   addObject(  moonPal,
            moonTiles,
            (uint32)moonPalLen,
            (uint32)moonTilesLen,
            (u16)150, (u16)50,
            32, 32,
            0,
            false,
            OBJCOLOR_16,
            OBJMODE_NORMAL,
            OBJPRIORITY_2,
            false,
            false);
    /* Display the backgrounds. */
    displayStarField();
    displayPlanet();
    displaySplash();
    /*
     *  Update the OAM.
     *
     *  We have to copy our copy of OAM data into the actual
     *  OAM during VBlank (writes to it are locked during
     *  other times).
     */
   swiWaitForVBlank();
   updateOAM(oam);
    return 0;
}


Last edited by TheMagnitude on Thu Mar 27, 2008 8:46 pm; edited 1 time in total

#153262 - TheMagnitude - Thu Mar 27, 2008 10:24 am

Actually none of the posX values seem to be working for the orange shuttle and the moon, they both appear as 0 on the DS.

#153267 - silent_code - Thu Mar 27, 2008 1:45 pm

did you test it with no$gba? try that.

#153271 - TheMagnitude - Thu Mar 27, 2008 2:59 pm

On no$gba everything looks fine. Also I forgot to mention that rotations were not working on the ds + DeSmuMe. But the rotations and palletes and coordinates seem to work on no$gba.

So things not working on DS:
>Xpos initial calls (if i use my function to add a sprite, then set the xpos after the function that seems to work)
>Rotation
>Palletes

This has been driving me daft for hours soon to be days. :(

#153277 - SiW - Thu Mar 27, 2008 5:19 pm

For one thing, change

Code:
tOAM *oam = new tOAM();


to

Code:
tOAM *oam;


and then in your actual main function, before the initOAM call, do

Code:
oam = new tOAM();

#153286 - silent_code - Thu Mar 27, 2008 6:37 pm

change
Code:
obj->rsMatrixIdx = ATTR1_ROTDATA(info->oamId);

to
Code:
obj->rsMatrixIdx = info->oamId;


another guy i helped had the exact same problem. that solved it. (i assume you have all the most recent tools, libs and emulators.)

the first line of code is the old way of doing things. libnds has a really clever SpriteEntry structure now, that doesn't need all the shifting and logic ops in the c/c++ code any more.

look at the struct, it reflects all possible usages and setups, as well as restrains of the hw objects very well.

it looks like the tutorial is incompatible with the current libnds version.

#153290 - TheMagnitude - Thu Mar 27, 2008 8:44 pm

Doing both of those things didnt seem to have any effect :(

The libnds version that I have is the version that comes with the latest release of devkitpro? Is that the latest version?

Also what seems to be quite strange is that the original tutorial code works on the DS absolutely fine!

EDIT: Ive updated the code for the first post as to not confuse things.

#153292 - silent_code - Thu Mar 27, 2008 9:54 pm

okay, send me the files and i'll fix it while i'm in the mood for it. ;^)
you got 20 minutes from now to contact me via pm, then the offer expires. i'll pm you an email adress or better yet, send me link to a .rar or .zip or something in the first place.

#153295 - silent_code - Thu Mar 27, 2008 10:44 pm

time is over... contact me anyway. might take longer until i respond, though. it's 10:44 pm here.

#153355 - TheMagnitude - Sat Mar 29, 2008 12:04 am

SOLVED!!! ;)