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 > clearing the screen using DMA

#35482 - headspin - Sat Feb 05, 2005 10:32 am

Does anyone have a clue how to do this? I saw some code that had the following line

Code:
// -- clear screen data
DMAClear(3, 0, VRAM, VRAM_SIZE, 16);


Unfortunately the actual function was not included in the source. Any ideas?
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game

#35486 - blinky465 - Sat Feb 05, 2005 1:08 pm

I was using something similar, but completely out of context.
There's a post on "clearing the screen" at http://forum.gbadev.org/viewtopic.php?t=4916

it gives a dma-based screen clearing function. It was no use to me, but if you're working in non-tiled mode, should be suitable.

#35495 - Cearn - Sat Feb 05, 2005 3:30 pm

The following thread may also be of some interest: http://forum.gbadev.org/viewtopic.php?t=1803

#35529 - headspin - Sun Feb 06, 2005 12:53 pm

Hmm... no joy, the code examples on those links are not for tile modes. Ok, I'll post some code I've been playing with..

Code:
#define BG0 0
#define BG1 1
#define BG2 2
#define BG3 3

#define TILE_DATA 2
#define TILE_MAP  8

#define TileDataAddr(n) (((n)*0x4000)+0x6000000)
#define TileMapAddr(n) (((n)*0x800)+0x6000000)
#define ColorPaletteAddr(n) (((n)*0x20)+0x5000000)

#define bg_data_addr(i) ((*(u16*)(0x4000008+(i*2)))>>TILE_DATA) & 0x3
#define bg_map_addr(i) ((*(u16*)(0x4000008+(i*2)))>>TILE_MAP) & 0x3


Here is my original map clearing function, where you simply say clear_bg(BG0); and works fine, but is much slower than if we use DMA...

Code:
void clear_bg(u8 bg)
{
   u16 loop=0;
   u16 x, y;
   u16 *pMap;

   pMap = (u16 *) TileMapAddr(bg_map_addr(bg));
   
   for (y = 0; y<32; y++)
   {
      for (x = 0; x<32; x++) pMap[loop++] = 0;
   }
}


And below is a very lame attempt at modifying the posted code from those links to clear a map instead of clearing screen pixels

Code:
void DMAClearMap(u8 bg) {
   REG_DM3SAD     = (u32) 0;
   REG_DM3DAD     = TileMapAddr(bg_map_addr(bg));      //Destination Address
   (REG_DM3CNT_L) = 64;
   (REG_DM3CNT_H) = 0x9100;
}


And no it dosn't work, it seems to write over the maps with 'junk'. Generally I place a blank tile in the first tile for each char base. So setting each tile map to zero should point it to a blank tile.
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game


Last edited by headspin on Sun Feb 06, 2005 8:45 pm; edited 2 times in total

#35530 - Cearn - Sun Feb 06, 2005 1:10 pm

headspin wrote:
Code:
void DMAClearMap(u8 bg) {
   REG_DM3SAD     = (u32) 0;
   REG_DM3DAD     = TileMapAddr(bg_map_addr(bg));      //Destination Address
   (REG_DM3CNT_L) = 64;
   (REG_DM3CNT_H) = 0x9100;
}

The source register of DMA needs an address, not a value. You're filling with the contents of address 0, not 0 itself.

#35532 - headspin - Sun Feb 06, 2005 2:40 pm

Hmm in that case..

Code:
const u16 BLANK_TILE = 0;

void DMAClearMap(u8 bg) {
   REG_DM3SAD     = (u32) &BLANK_TILE;
   REG_DM3DAD     = TileMapAddr(bg_map_addr(bg));      //Destination Address
   (REG_DM3CNT_L) = 64;
   (REG_DM3CNT_H) = 0x9100;
}


Renders a black screen but then stops anything from displaying on the screen thereafter. Same problem the guy was having who used the function from those links.

I'm guessing DMA copying uses REG_DM3SAD as a *starting* address and will copy the number of bytes (or whatever size it copies) from REG_DM3CNT_L. Which would mean I would have to have an array of zeros that size stored somewhere as the source. Unless I find an area in ROM or RAM I know is going to be blank. Perhaps I could allocate some in IWRAM to make it even faster.

I still don't see why it stops everything else from displaying on the screen afterwards using the code above.

Time to do some researching I think... get out my dusty old Cowbites print out and a cup of coffee ;) My GBA skills have gotten rusty, must have been all the XMas drinking from last year! Talk about a DMAClear() to my brain. I'm might also check out that swi 0xc BIOS function while I'm at it.
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game

#35533 - Cearn - Sun Feb 06, 2005 2:50 pm

headspin wrote:
<snip>
Code:
   (REG_DM3CNT_H) = 0x9100;
</snip>
IIRC, 0x9100 means :
0x8000 : DMA_ENABLE
0x1000 : transfer on vblank
0x0100 : fixed source address.
which would wipe the screen at every vblank. Shouldn't that be 0x8100?

#35538 - blinky465 - Sun Feb 06, 2005 8:10 pm

headspin wrote:
Renders a black screen but then stops anything from displaying on the screen thereafter.

I've also had this problem using dma screen blanking - which I why I shy away from it now! It think it was something to do with clearing vram completely and wiping out all my sprites/objects(?) or was it the palettes?

#35539 - headspin - Sun Feb 06, 2005 8:42 pm

Cearn wrote:
headspin wrote:
<snip>
Code:
   (REG_DM3CNT_H) = 0x9100;
</snip>
IIRC, 0x9100 means :
0x8000 : DMA_ENABLE
0x1000 : transfer on vblank
0x0100 : fixed source address.
which would wipe the screen at every vblank. Shouldn't that be 0x8100?


Well I'll be darned, it bloody worked!

And I can totally see (or should I say hear) the difference. There was a buzz in the audio before when clearing the maps... that's now gone cos its very fast. Perfect! Thanks :)

So there ya go blinky, give my code a try if you like!
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game