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 > Understanding DMA Registers

#34834 - kareemjg - Wed Jan 26, 2005 11:23 pm

Okay.. I'm a little new to GBADEV so bare with me. Basiclly what I am doing is buidling my own engine for learning puroses by studying the sources and incorprating what I learn into the code.

My question is pertaining to putting text to the screen. I can do it but I'm trying to get a better understand what I am emulating. Studying one of the source programs I see the following functions:
Code:

void DMACopyCH0(void* source, void* dest, u32 WordCount, u32 mode) {
    REG_DM0SAD = (u32)source;      //Tell the gba our source address
    REG_DM0DAD = (u32)dest;        //Tell the gba where the data should get copied to
    REG_DM0CNT = WordCount | mode; //Set the mode
}

void DMACopyCH1(void* source, void* dest, u32 WordCount, u32 mode) {
    REG_DM1SAD = (u32)source;
    REG_DM1DAD = (u32)dest;
    REG_DM1CNT = WordCount | mode;
}

void DMACopyCH2(void* source, void* dest, u32 WordCount, u32 mode) {
    REG_DM2SAD = (u32)source;
    REG_DM2DAD = (u32)dest;
    REG_DM2CNT = WordCount | mode;
}

void DMACopyCH3(void* source, void* dest, u32 WordCount, u32 mode)
{
    REG_DM3SAD = (u32)source;
    REG_DM3DAD = (u32)dest;
    REG_DM3CNT = WordCount | mode;
}


Is this stating that the device has allocated four differnt memory slots to hold indivdual font types? Or is my line of reasoning off.

#34839 - ScottLininger - Thu Jan 27, 2005 1:22 am

DMA stands for Direct Memory Access. It's a method by which the gameboy hardware can shuffle large chunks of memory from one location to another. So if you want to copy a big block of graphics from ROM to the video ram, for example, DMA is a fast way to do it.

DMA registers control all of this stuff. You poke a few values into the registers, and BAM! The GB starts copying.

DMA has several "channels" that are numbered in order of priority. A DMA1 will be transferred before a DMA3. All that your posted code does is abstract the register access into some friendly functions. So it doesn't have anything specifically to do with fonts or text. It's just an alternate way to move memory around. We'd need to see the "context" of these function calls to help much with how it's contributing to a font engine.

By the way, the gameboy doesn't really natively support anything like fonts. Though the tile modes are sometimes referred to as "text modes," that's only really a good term if you take it in terms of the old DOS text video modes. When someone says "fonts" on the gameboy, they generally mean "tile sets." Granted, this is just a matter of semantics, but shifting your perspective to be more about pixels and less about fonts might help to make sense of the code you're looking at.

My favorite source for "low level" GB info is the cowbite spec, which goes over all of the registers in great detail. And if you haven't already, definitely read the FAQ under the beginner's forum.

Hope that helps! :)

-Scott

#34844 - kareemjg - Thu Jan 27, 2005 1:53 am

The source came from the website and can be found here: http://www.gbadev.org/download.phpsection=demos&filename=textdma.zip

DMA is still pretty new to me but I am understanding. I understand about the fonts being generated from spliced images in much the same way as sprites. What I was trying to understand is the function behind what the code author was doing when he defined the various DMACopyCH0 - CH3. I understand the majority of the code but this is stumping me and I just cant seem to leave it until I figure it out.

On a side note what do the double carrots evaluate as. Example
Code:
REG_DISPCNT = (1<<8);
.

At this point I would usally make some snappy remark offering an excuse on my igornace but at this point I guess the only way to learn is by asking. :)

Thanks for help.

-kareem

#34852 - LOst? - Thu Jan 27, 2005 4:35 am

kareemjg wrote:
On a side note what do the double carrots evaluate as. Example
Code:
REG_DISPCNT = (1<<8);



<< means bitwise shift left.

Move bit 1 eight times to the left.
This is done in binary.

I never use the constant (1 << 8). I do the same as the compiler do writing it in hex:
0x100


To be a little bit more informative. If you have the binary value of 1 in a word, it looks like this:
Code:

0000000000000001  binary value
fedcba9876543210  bit order


And shifting this value by 1 (operator<< 1) will result in this value:
Code:

0000000000000010  binary value
fedcba9876543210  bit order


And shifting the original value by 8 (operator<< 8) will result in this value:
Code:

0000000100000000  binary value
fedcba9876543210  bit order


Now to help you a little bit more. The operator | is called bitwise OR. It is used in this code:
Code:

REG_DM3CNT = WordCount | mode;

Let's say WordCount is 255 (hex 0xFF) and mode is 256 (hex 0x100), this is the values in binary:
Code:

WordCount's value:
0000000111111111  binary value
fedcba9876543210  bit order

Code:

mode's value:
0000001000000000  binary value
fedcba9876543210  bit order


Now ORing the two values:
Code:

ORing will combine the two values:
    0000000111111111
 OR 0000001000000000
 -------------------
    0000001111111111  Result

#34853 - kareemjg - Thu Jan 27, 2005 5:21 am

Thanks. The information about the bit shifting was most helpful. I knew about the hex coding but it was the first time I ran across it notated in that fashion.

-kareem

#34872 - kareemjg - Thu Jan 27, 2005 4:52 pm

Okay.. just want to make sure I'm understanding this right. Here is a bit of code I'm studying. I'm also refering to Cowbites Virtual Hardware Specs for the matchup.

Code:
   
   REG_DISPCNT = (1<<8);
   REG_BG0CNT = 0x80 | (21 << 8) | (0 << 2);



As Lost(r) point out I now understand (1<<8). So when the the value was set in REG_DISPCNT is was setting up Background 0 as I have defined in my gba.h file as #define BG0_ENABLE 0x100 .

Okay the next step I know it is setting up the control for Backround O. (XREF the Cowbyte sheet now)

so if we add up 0x80 | 21 << 8 | 0 << 2 it would eval as

0000 1000 0000
0101 0000 0000
0000 0000 0000
-------------------
0101 1000 0000

which would be 0x580; which would mean per the docs that

* Starting address of character tile data
Address = 0x6000000 + S * 0x4000 (with s equaling 5)

* also a front background with 3 priority

Did i read this right? Here are the docs for ref below.

Quote:

Address: 0x4000008 - REG_BG0CNT
Address: 0x400000A - REG_BG1CNT
Address: 0x400000C - REG_BG2CNT
Address: 0x400000E - REG_BG3CNT

These addresses set up the four background layers. The format is:

?
F E D C B A 9 8 7 6 5 4 3 2 1 0
Z Z V M M M M M A C X X S S P P

0-1 (P) = Priority - 00 highest, 11 lowest
Priorities are ordered as follows:

"Front"
1. Sprite with priority 0
2. BG with priority 0

3. Sprite with priority 1
4. BG with priority 1

5. Sprite with priority 2
6. BG with priority 2

7. Sprite with priority 3
8. BG with priority 3

9. Backdrop
"Back"

When multiple backgrounds have the same priority, the order
from front to back is: BG0, BG1, BG2, BG3. Sprites of the same
priority are ordered similarly, with the first sprite in OAM
appearing in front.

2-3 (S) = Starting address of character tile data
Address = 0x6000000 + S * 0x4000
6 (C) = Mosiac effect - 1 on, 0 off

7 (A) = Color palette type -
1 - standard 256 color pallete
0 - each tile uses one of 16 different 16 color palettes (no effect on
rotates/scale backgrounds, which are always 256 color)

8-C (M) = Starting address of character tile map
Address = 0x6000000 + M * 0x800
D (V) = Screen Over. Used to determine whether rotational backgrounds get tiled
repeatedly at the edges or are displayed as a single "tile" with the area
outside transparent. This is forced to 0 (read only) for backgrounds
0 and 1 (only).

E-F (Z) = Size of tile map
For "text" backgrounds:
00 : 256x256 (32x32 tiles)
01 : 512x256 (64x32 tiles)
10 : 256x512 (32x64 tiles)
11 : 512x512 (64x64 tiles)

For rotational backgrounds:
00 : 128x128 (16x16 tiles)
01 : 256x256 (32x32 tiles)
10 : 512x512 (64x64 tiles)
11 : 1024x1024 (128x128 tiles


-kareem