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.

Beginners > OAM copy?

#17566 - teezeCrost - Wed Mar 10, 2004 9:14 am

Hey folks. Hoping someone can help a newbie out; I'm just trying to decipher what is happening in this tutorial I'm reading. Here's the code I'm reading:

Code:
//create an OAM variable and make it point to the address of OAM
u16* OAM = (u16*)0x7000000;

//create the array of sprites (each one is a struct containing 4 attributes)
OAMEntry sprites[128];

//Copy our sprite array to OAM
void CopyOAM()
{
   u16 loop;
   u16* temp;
   temp = (u16*)sprites;
   for(loop = 0; loop < 128*4; loop++)
   {
      OAM[loop] = temp[loop];
   }
}


So I get that temp is a pointer to the 'sprites' array, and that each array element has 4 attributes.. but why loop (128*4) times? nothing in the temp array exists past [128]! How is temp[512] accessing anything?
is that some way of accessing the next memory address?
I'm new to C to, so please bear with me.
_________________
If you think you think outside the box, you're trapped in one.
-teezeCrost

#17569 - Lupin - Wed Mar 10, 2004 12:24 pm

you answered the question yourself...

It is just because OAMEntry is different size than u16... maybe you should use a 32 bit DMA copy, i think that would be faster.

#17577 - poslundc - Wed Mar 10, 2004 3:31 pm

Data types are extremely important in C.

Compare the size of a u16 to the size of an OAMEntry.

Then realize that your temp variable is a u16 pointer, not an OAMEntry pointer, even though they point to the same location in memory.

Lupin: There's no way he should be fussing around with the DMA before he understands how a basic memory transfer works. I don't know where you got this notion of yours that speed is so important that you should obfuscate the process.

Dan.

#17578 - Lupin - Wed Mar 10, 2004 3:36 pm

this will copy with dma...

Code:

#define REG_DMA3SAD               (*(vu32*)0x40000D4)
#define REG_DMA3DAD               (*(vu32*)0x40000D8)
#define REG_DMA3CNT               (*(vu32*)0x40000DC)

#define DMA_ENABLE               0x80000000
#define DMA_TIMEING_IMMEDIATE      0x00000000
#define DMA_32                  0x04000000

#define DMA_32NOW               DMA_ENABLE | DMA_TIMEING_IMMEDIATE |DMA_32
#define DMA_16NOW               DMA_ENABLE | DMA_TIMEING_IMMEDIATE |DMA_16

#define DMACopyCH3(source,dest,wc,mode)      REG_DMA3SAD = (u32)source; \
                                   REG_DMA3DAD = (u32)dest; \
                                   REG_DMA3CNT = wc | mode;
//Copy sprite array to OAM
void CopyOAM() {
   DMACopyCH3((u32*)sprites,OAM,256,DMA_32NOW);
}


I know what you mean pos, but he needs to learn dma anyway... I find the DMA way less confusing, this way it is obvious that you copy 256 32 bit values...

#17588 - sajiimori - Wed Mar 10, 2004 7:30 pm

You may find DMA less confusing, but iterating over arrays uses only standard C functionality, and is far more general. If someone is going to develop in C, they'd better know the language first.

#17593 - Lupin - Wed Mar 10, 2004 8:47 pm

If someone is going to develop for the GBA, they'd better know the hardware first. ;P

he may choose what he find better by himself...

#17595 - teezeCrost - Wed Mar 10, 2004 9:21 pm

First of all, thanks for the responses!
Now, in the following can someone solidify what exactly is being done? With the little experience I have, I would say that temp is pointing to a version of the sprites array that is being type casted as a pointer to an unsigned 16bit int.. How far off am I?

Code:
temp = (u16*)sprites;


but then here

Code:
OAM[loop] = temp[loop];


it seems to access temp as if it were a different (than sprites[]) array altogether, which leads me to think that (u16*) is telling it to just point to 16bit chunks.

Obviously the copy of C for dummies that's been on my shelf for years isn't cutting it. Any suggestions for other newbie-friendly yet thorough books? possibly something that will also touch on c++?
_________________
If you think you think outside the box, you're trapped in one.
-teezeCrost

#17597 - Lupin - Wed Mar 10, 2004 9:38 pm

OAM is a 16 bit pointer, sprites is a custom structure. We need the typecast to transfer our custom structure to the 16bit values OAM is pointing to. That's why we need a typecast to temp.

I am using 32 bit pointers in my dma version because moving 32 bit is faster than moving 16 bit (you move twice the data in nearly the same time).

So, you were right with temp being a 16 bit pointer and OAM is a 16 bit pointer too.

#17599 - teezeCrost - Wed Mar 10, 2004 10:14 pm

Ok so when type casting a variable to a pointer of some number of bits, is the result always accessed as an array?
Also, I'm pretty sure I know what the DMA stands for, but could you tell me anyway?
_________________
If you think you think outside the box, you're trapped in one.
-teezeCrost

#17600 - Lupin - Wed Mar 10, 2004 10:39 pm

DMA = direct memory access, very fast way to copy data (it is using the GBA hardware)

When you typecast to a pointer you can access it as you want, depending on how you type casted it. You can typecast to a pointer and then dereference by using the * operator...:

bla = foo*;

is the same as...

bla = foo[0];

where foo is some valid pointer

#17601 - poslundc - Wed Mar 10, 2004 10:45 pm

teezeCrost wrote:
Ok so when type casting a variable to a pointer of some number of bits, is the result always accessed as an array?


Pointers are pointers. They just point to a location in memory. Whether you have a pointer to a u32, a s16, or some other struct, it's just a number that says where in memory some data is located.

You dereference a pointer by using the dereference operator *. This tells the compiler to go look up and access the value stored in the pointer. This is where the data type comes in: if it's a u16 then the data is interepreted as a 16-bit unsigned number. If it's a struct, it's interpreted as the fields of the struct.

You can also dereference a pointer by using square (array) brackets. Eg. *p is the same as p[0]. If I use p[1] instead of p[0], it uses the size of the type of "p" to figure out how many bytes further in memory to advance from the pointer "p".

What's important to understand is that typecasting from one type of pointer to another doesn't change that it is still fundamentally just a pointer to a location in memory. It just changes how the data located at that spot in memory is interpreted.

Quote:
Also, I'm pretty sure I know what the DMA stands for, but could you tell me anyway?


Please refer to Day 5 of the Pern Project Tutorials.

Dan.

#17617 - teezeCrost - Thu Mar 11, 2004 4:44 am

Thanks for everyone's help! I think I actually get it now!
_________________
If you think you think outside the box, you're trapped in one.
-teezeCrost

#17621 - sajiimori - Thu Mar 11, 2004 5:56 am

Quote:

If someone is going to develop for the GBA, they'd better know the hardware first. ;P

I think it's ok to learn by doing as far as the hardware goes, but I agree with tepples that C is a prerequisite for GBA development (if that is to be your language).
Quote:

he may choose what he find better by himself...

Yes, and I agree that DMA is better in this circumstance, but that was not my point.

Anyway, quick note about the [] operator: a[i] is merely shorthand for *(a + i). They are interchangable in all circumstances, so the [] operator is only for readability.

#17629 - Lupin - Thu Mar 11, 2004 3:31 pm

sajimori, *(a+i) is not the same as a[i], only if a is a byte pointer (or am i wrong?!).

#17631 - poslundc - Thu Mar 11, 2004 3:44 pm

Lupin wrote:
sajimori, *(a+i) is not the same as a[i], only if a is a byte pointer (or am i wrong?!).


Yes, you are wrong. (Try googling pointer arithmetic.)

Dan.