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.

C/C++ > Loop using different types

#107767 - QuantumDoja - Wed Nov 01, 2006 9:11 pm

Hi, I have an array that holds whether a location in memeory is full, it is defined as:

Code:
u16 OAMArray[7];


my array has the following values set:
Code:

OAMArray[0] = 1; //full
   OAMArray[1] = 1; //full
   OAMArray[2] = 0;
   OAMArray[3] = 0;
   OAMArray[4] = 0;
   OAMArray[5] = 0;
   OAMArray[6] = 0;
   OAMArray[7] = 0;
-

I can then have this loop see if a memeory location is full, if so, get the next free slot.
Code:

int f = 0;
               for (k = 0; k < 8; k++) {
                  if (f == 0) {
                     if (OAMArray[k] == 0) {
                        OAMArray[k] = 1; //set full.
                        OAMPtr = k;
                        f = 1;
                     }
                  }
               }


the issue is, If my array is not u16 it doesnt work and i dont know why, I have tried my array as u8,int and u32 all produce different results....i just want to have an array of 0 or 1! - should i be using u16's??
_________________
Chris Davis

#107768 - sajiimori - Wed Nov 01, 2006 9:17 pm

You're overrunning your array. You allocated 7 elements, but you wrote to the 8th one. If you declare an array with n elements, don't index past n-1.

#107786 - gmiller - Wed Nov 01, 2006 11:56 pm

If you only need 1 or zero then this "array" could be in one 32 bit int (32 1 bit flags). Here are some macros that might be be helpful:
Code:

#define setBitu32(arName,bitNum) arName[(bitNum) >> 5] &= (1 << ((bitNum) & 31))
#define clrBitu32(arName,bitNum) arName[(bitNum) >> 5] &= ~(1 << ((bitNum) & 31))
#define tstBitu32(arName,bitNum) arName[(bitNum) >> 5] |= (1 << ((bitNum) & 31))


Then to use it:
Code:

unsigned int OAMarray[1];

OAMarray[0] = 0; //clear all 32 bits

setBitu32(OAMarray, 0); // set bit zero
setBitu32(OAMarray, 1); // set bit One

int f = 0;

for (k = 0; k < 7; k++) { // search 7 elements (0 - 6)
  if (tstBitu32(OAMarray, k) == 0) {
     setBitu32(OAMarray, k);
     break;
  }
}

if (f != 0) { // found
 }


There may be a typo here I just did this without compiler checking but I believe it is correct.

#107795 - sajiimori - Thu Nov 02, 2006 1:17 am

If you eventually go the bitfield route, figure out how to do it by hand, and then immediately stop doing it by hand, and instead start compiling as C++ (if you're not already) and use the std::bitset class. Even if you use no other C++ features, this one will save you a lot of headache at practically zero cost.

#107802 - gmiller - Thu Nov 02, 2006 4:31 am

I agree somewhat with the bitfield use as sajiimori says but I have found that most iplementations of bitfields just "suck" so I stopped using them. The bit fields in C are 3 to four times the code size they need to be and at least twice as slow as doing them by hand. My experience with bit fields in C++ was pretty bad so I stopped using them as well. But to be fair that was 10 years ago so their might have been changes that would change my mind. To me doing it by hand is zero cost at this time so I continue to do it that way. I guess I am just scary that way ...

#107823 - sgeos - Thu Nov 02, 2006 10:59 am

I'd write a clearArrayU16() function, and then do something like this:
Code:
// Prototype
void clearArrayU16(u16 *pData, int pSize, u16 pClear);

#define OAM_ARRAY_SIZE 8
u16 OAMArray[OAM_ARRAY_SIZE];

clearArrayU16(OAMArray, OAM_ARRAY_SIZE, 0);
OAMArray[0] = 1;

If you want to set the first four elements, you can do this instead:
Code:
clearArrayU16(OAMArray, OAM_ARRAY_SIZE, 0);
clearArrayU16(OAMArray, 4, 1);

Or if you want to skip the first element and set the four after that:
Code:
clearArrayU16(OAMArray, OAM_ARRAY_SIZE, 0);
clearArrayU16(&OAMArray[1], 4, 1);

Note that you can easily overrun your array if you are not careful.
You'll have to write the clear function yourself. For what it's worth, you've basically written it already.

-Brendan

#107833 - QuantumDoja - Thu Nov 02, 2006 1:22 pm

Thanks for your replies, I may use the bitfield, but have just found through countless iterations of trial and error that if i do this:
Code:
__attribute__((section (".ewram")))  int OAMArray[8];


it works fine, so maybe i was having a memory overwrite issue???
_________________
Chris Davis

#107835 - gmiller - Thu Nov 02, 2006 2:01 pm

QuantumDoja wrote:
Thanks for your replies, I may use the bitfield, but have just found through countless iterations of trial and error that if i do this:
Code:
__attribute__((section (".ewram")))  int OAMArray[8];


it works fine, so maybe i was having a memory overwrite issue???


Just remember that the array you are declaring uses subscripts 0 - 7. By default the data would be in EWRAM anyway so you may be just over writting something else by the directive use.

#107875 - sajiimori - Thu Nov 02, 2006 7:35 pm

QuantumDoja, perhaps you missed my post, because I already told you about the array length. :)

gmiller, I agree that bitfields are not fast on most compilers, but I was talking specifically about std::bitset. Have you ever used it?

#107878 - gmiller - Thu Nov 02, 2006 8:17 pm

I used an early implementation on SUN Solaris and it's performace was so bad we removed it and did the work with macros and it was 500% faster and 50% the size. But ... that was 10 years ago so I don't know now. I guess I should look at it again. I don't use C++ that often because of the way it works but there are application types where it is just a must "GUI". Since most of what I write is background processing I don't need the features that often and when I do I usually just put C++ wrappers around the C. Not a generally recommended way of approaching the problem space but it works for me.

#107896 - sajiimori - Thu Nov 02, 2006 11:21 pm

Yeah, a lot has happened in the compiler world since then. :)