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.

Coding > trying to get graphics to show up in the screen right

#149770 - yaazz - Fri Jan 25, 2008 3:33 am

Hey everyone I am back again. I am trying to get a picture (All the picture is is 4 rectangles of different colors that should fill the screen) to scroll around on the GBA screen.

I am again using the book "Programming the Nintendo Game Boy Advance"
The rectangle scrolls just fine, but is being sheared to the right for some reason. It also looks completely wrong vertically, with all green for a few pixels......

hopefully someone can help me out...

The code is pretty much copy and pasted from the pdf..
Here it is

Code:

////////////////////////////////////////////////////////////
// Programming The Game Boy Advance
// Chapter 6: Tile-Based Video Modes
// TileMode0 Project
// main.c source code file
////////////////////////////////////////////////////////////
//include the sample tileset/map
#include "colorz.pal.c"
#include "colorz.map.c"
#include "colorz.raw.c"


#define MULTIBOOT int __gba_multiboot;
MULTIBOOT



//function prototype
void DMAFastCopy(void*, void*, unsigned int, unsigned int);

//defines needed by DMAFastCopy
#define REG_DMA3SAD *(volatile unsigned int*)0x40000D4
#define REG_DMA3DAD *(volatile unsigned int*)0x40000D8
#define REG_DMA3CNT *(volatile unsigned int*)0x40000DC
#define DMA_ENABLE 0x80000000
#define DMA_TIMING_IMMEDIATE 0x00000000
#define DMA_16 0x00000000
#define DMA_32 0x04000000
#define DMA_32NOW (DMA_ENABLE | DMA_TIMING_IMMEDIATE | DMA_32)
#define DMA_16NOW (DMA_ENABLE | DMA_TIMING_IMMEDIATE | DMA_16)

//scrolling registers for background 0
#define REG_BG0HOFS *(volatile unsigned short*)0x4000010
#define REG_BG0VOFS *(volatile unsigned short*)0x4000012

//background setup registers and data
#define REG_BG0CNT *(volatile unsigned short*)0x4000008
#define REG_BG1CNT *(volatile unsigned short*)0x400000A
#define REG_BG2CNT *(volatile unsigned short*)0x400000C
#define REG_BG3CNT *(volatile unsigned short*)0x400000E
#define BG_COLOR256 0x80
#define CHAR_SHIFT 2
#define SCREEN_SHIFT 8
#define WRAPAROUND 0x1

//background tile bitmap sizes
#define TEXTBG_SIZE_256x256 0x0
#define TEXTBG_SIZE_256x512 0x8000
#define TEXTBG_SIZE_512x256 0x4000
#define TEXTBG_SIZE_512x512 0xC000

//background memory offset macros
#define CharBaseBlock(n) (((n)*0x4000)+0x6000000)
#define ScreenBaseBlock(n) (((n)*0x800)+0x6000000)

//background mode identifiers
#define BG0_ENABLE 0x100
#define BG1_ENABLE 0x200
#define BG2_ENABLE 0x400
#define BG3_ENABLE 0x800

//video identifiers
#define REG_DISPCNT *(unsigned int*)0x4000000
#define BGPaletteMem ((unsigned short*)0x5000000)
#define SetMode(mode) REG_DISPCNT = (mode)

//vertical refresh register
#define REG_DISPSTAT *(volatile unsigned short*)0x4000004

//button identifiers
#define BUTTON_RIGHT 16
#define BUTTON_LEFT 32
#define BUTTON_UP 64
#define BUTTON_DOWN 128
#define BUTTONS (*(volatile unsigned int*)0x04000130)

//wait for vertical refresh
void WaitVBlank(void)
{
    while((REG_DISPSTAT & 1));
}

////////////////////////////////////////////////////////////
// Function: main()
// Entry point for the program
////////////////////////////////////////////////////////////
int main(void)
{
    int x = 0, y = 0;
    int n;

    //create a pointer to background 0 tilemap buffer
    unsigned short* bg0map =(unsigned short*)ScreenBaseBlock(31);

    //set up background 0
    REG_BG0CNT = BG_COLOR256 | TEXTBG_SIZE_256x256 |(31 << SCREEN_SHIFT) | WRAPAROUND;

    //set video mode 0 with background 0
    SetMode(0 | BG0_ENABLE);

    //copy the palette into the background palette memory
    DMAFastCopy((void*)colorz_Palette, (void*)BGPaletteMem,256, DMA_16NOW);

    //copy the tile images into the tile memory
    DMAFastCopy((void*)colorz_Tiles, (void*)CharBaseBlock(0),640, DMA_32NOW);

    //copy the tile map into background 0
    DMAFastCopy((void*)colorz_Map, (void*)bg0map, 256, DMA_32NOW);

//main game loop
while(1)
{

    //wait for vertical refresh
    WaitVBlank();

    //D-pad moves background
    if(!(BUTTONS & BUTTON_LEFT)) x--;
    if(!(BUTTONS & BUTTON_RIGHT)) x++;
    if(!(BUTTONS & BUTTON_UP)) y--;
    if(!(BUTTONS & BUTTON_DOWN)) y++;

    //use hardware background scrolling
    REG_BG0VOFS = y ;
    REG_BG0HOFS = x ;

    //wait for vertical refresh
    WaitVBlank();
    for(n = 0; n < 4000; n++);
    }
    return 0;
}

////////////////////////////////////////////////////////////
// Function: DMAFastCopy
// Fast memory copy function built into hardware
////////////////////////////////////////////////////////////
void DMAFastCopy(void* source, void* dest, unsigned int count,unsigned int mode)
{
    if (mode == DMA_16NOW || mode == DMA_32NOW)
    {
        REG_DMA3SAD = (unsigned int)source;
        REG_DMA3DAD = (unsigned int)dest;
        REG_DMA3CNT = count | mode;
    }
}



And the picture files

colors.raw.c
Code:

//
// colorz (640 uncompressed bytes)
//
const unsigned char colorz_Tiles[640] = {
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x04, 0x04,
0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x04, 0x04,
0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x04, 0x04,
0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05,
0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05,
0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05,
0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05,
0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05,
0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05,
0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x01
};


colorz.map.c
Code:

/*
 * 8x32 map data
 */
const unsigned short colorz_Map[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
0x0000, 0x0001, 0x0002, 0x0003, 0x0004,0x0000, 0x0001, 0x0002,
};


colorz.pal.c
Code:

const unsigned short colorz_Palette[256] = {
0x0000, 0x0010, 0x001f, 0x03e0, 0x03ff, 0x7c00, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
};

#149786 - Dwedit - Fri Jan 25, 2008 9:14 am

Unless you love killing off your batteries, get rid of that WaitVBlank function ASAP, and forget you ever saw that version. Spinning the CPU on the DISPSTAT register is 100% CPU usage, and eats up lots of power. Instead, you should use the BIOS halt functions to wait for an interrupt.
The only rule is that you must install an interrupt handler before you can use the wait vblank functions. I think it's time to break out Libgba, because it makes it very easy to get an interrupt handler up and running quickly.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."

#149802 - yaazz - Fri Jan 25, 2008 2:47 pm

Interesting, I was wondering why CPU usage was 100% on my computer... I never even thought of battery life. Thanks for pointing that out

Back to the topic at hand. I have a screenshot of what is happening and what it is supposed to look like
[Images not permitted - Click here to view it]

I am quite certain that the problem lies in my not copying the correct amount of bytes with the DMA functions, but the book "Programming the Nintendo Game Boy Advance" doesn't state how many there should be!
I just guessed you input the size of the array, but that doesn't seem to work

#149803 - Dwedit - Fri Jan 25, 2008 2:50 pm

Your tilemap is 240 wide, a GBA's tilemap is 256 wide.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."

#149810 - Kyoufu Kawa - Fri Jan 25, 2008 3:33 pm

"Programming the Nintendo Game Boy Advance" is bad for you. Try this.

#149817 - gmiller - Fri Jan 25, 2008 5:36 pm

Also

#define REG_DISPCNT *(unsigned int*)0x4000000

should be

#define REG_DISPCNT *(unsigned short*)0x4000000

among other things. The material is so full of bugs and bad practices I discourage my students from reading it except for entertainment.

#150247 - yaazz - Fri Feb 01, 2008 12:45 am

I appreciate the advice, but does anyone know what I can do to fix the problem in the topic?

#150249 - gmiller - Fri Feb 01, 2008 1:23 am

Your DMA's are trying to move too much data based on your data.
Code:

//copy the tile images into the tile memory
    DMAFastCopy((void*)colorz_Tiles, (void*)CharBaseBlock(0),640, DMA_32NOW);

    //copy the tile map into background 0
    DMAFastCopy((void*)colorz_Map, (void*)bg0map, 256, DMA_32NOW);


Each of these is trying to move some number of 32 bit values when based on your data the numbers you put in are for 16 bit values. So ... you either need to half the number of elements you are tring to move or change DMA_32NOW to DMA_16NOW.

This will correct the data transfer but I do not know if it will fix it all.

#150487 - yaazz - Tue Feb 05, 2008 6:27 pm

thanks gmiller, that helped but didnt fix the problem entirely. It still appears to be skewed slightly to the right.
From reading the TONC tutorial, I see that you can have your bitmaps in 8bpp or 16bpp. Could part of the problem be that my bitmap is set to 8pp, but the hardware is set to 16 causing a double pixel write?

#150491 - Kyoufu Kawa - Tue Feb 05, 2008 8:20 pm

I can imagine loading an 8bpp image in a 16bpp mode to give some problems, yeah...

#150495 - Cearn - Tue Feb 05, 2008 9:10 pm

yaazz wrote:
thanks gmiller, that helped but didnt fix the problem entirely. It still appears to be skewed slightly to the right.
From reading the TONC tutorial, I see that you can have your bitmaps in 8bpp or 16bpp. Could part of the problem be that my bitmap is set to 8bpp, but the hardware is set to 16 causing a double pixel write?

You're not working with bitmaps here, you're working with tilemaps and GBA tilemaps only use 4bpp or 8bpp graphics. If you had a mismatch between the graphics bitdepth and how the hardware uses the data, you'd sooner see something like this, not just shifted graphics.

When graphics are shifted, it usually means that the source width isn't the same as the destination width. The data is always stored as a linear array, the bitmap will appear by how you group this data into two dimensions. For example, you can have 3*5=15 items stored linearly as:

111222333444555

If width=3, you will see:
111
222
333
444
555

but if width=5, you see
11122
23334
44455


The original data is the same, but the 2D interpretation is different. This is what is probably happening in your case: the source bitmap has a width of 240 (30 tiles), but, as Dwedit said, the GBA tilemaps has a width of 256 (32 tiles). Pad your bitmap to 256 pixels wide or copy each scanline separately.


The earlier problem with DMA_16 vs DMA_32 wasn't the bitdepth of the data you're copying, it's how much data is copied each DMA-step and in total: DMA_16 copies per 2 bytes for a total of count*2, DMA_32 uses 4 bytes each step for a total of count*4. DMA doesn't actually care about or change what you're copying, but you do have to take care that it copies the correct amount.

#150517 - Cydrak - Wed Feb 06, 2008 1:21 am

If you installed devkitPro, have you seen libgba and the working examples which came with it? TONC also comes with libraries and plenty of code to match the text, if that's easier to follow. Particularly see the "tonc-code.zip\code\basic\brin_demo\" project (and matching section on tiled backgrounds) which looks like what you're trying to do.

Hmm. As mentioned, that text has no shortage of serious problems... but lemme see.
Code:
void WaitVBlank(void) {
    while((REG_DISPSTAT & 1));
}

Bit 0 is set during vblank. So besides burning power, this waits for vblank to end. Outside of vblank, it does nothing at all. As a bonus, the compiler may see the empty for() "delay," and feel it has every right to toss it out. :-)

So I think while() is running full tilt here, during draw time (exactly when you don't want it to). If it "tears up" when you try to scroll, that would be why. Anyway, both libraries I mentioned provide a working function. You just need to #include the right header, enable the vblank interrupt, and call VBlankIntrWait() between frames. (I could be wrong, but I don't think a handler is required, they seem to use a dispatcher and ack interrupts by default.)

Also watch out for the register #defines, some of them look a bit dodgy (REG_DISPCNT and WRAPAROUND are clearly wrong, don't know about the others). This is pretty fundamental stuff, and another point in favor of the libraries... bugs here will just lead to lots of confusion and hair loss. (Especially if the code using the #defines is otherwise correct!)

#150524 - yaazz - Wed Feb 06, 2008 3:28 am

Cearn you are a god. That fixed my problem!
There is still a bunch of crap on the bottom but I assume this is also a byproduct of not enough tiles