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++ > struct with variables being a ceratin bit size.

#19206 - mr_schmoe - Wed Apr 14, 2004 1:56 am

Ok, here's the idea. In pascal, you can define a record (or struct in C) where each member is a certain number of bits. And, I want to do something like that in C. For example you have the struct for the OAM defined as:
Code:
typedef struct tagSprite
{
        u16 attribute0;
        u16 attribute1;
        u16 attribute2;
        u16 attribute3;
}Sprite;


And I want the struct to look like this:
Code:
typedef struct tagSprite
{
        7bits yCoordinate;
        1bits rotateflag;
        1bits doublesize;
        2bits alphablending;
        ...
        3bits palettenum;
}Sprite;


And have it still only be 4 bytes long. Is there a way to do that?

Of course, on the other hand, you could just take the attribute in question and isolate the bits with the info you want, shift it over and there's you data, but that's complicated and I'm not sure exactly on how to do that. If someone out there has the idea, that would work also.

#19208 - sajiimori - Wed Apr 14, 2004 2:18 am

C does support bitfields, but they're not very fast on GCC and they aren't guaranteed to have any particular arrangement (so they might not match hardware, if that's what you're thinking).
Code:

typedef struct tagSprite
{
        u16 yCoordinate : 7;
        u16 rotateflag : 1;
        u16 doublesize : 1;
        u16 alphablending : 2;
        ...
        u16 palettenum : 3;
}Sprite;

I'd suggest using plain shifts -- it's not that complicated. Just a macro for each bitfield.

#19209 - sgeos - Wed Apr 14, 2004 2:30 am

Use bit fields. Here is some rgb example code that uses bit fields:
Code:
/*** Compile Options
 *
gcc -Wall -o pack pack.c -fpack-struct
 */

#include <stdio.h>

#define RGB_T_BIT_DEPTH         5

typedef unsigned int    rgb_color_t;

typedef struct rgb_t {
        rgb_color_t     red:    RGB_T_BIT_DEPTH;
        rgb_color_t     green:  RGB_T_BIT_DEPTH;
        rgb_color_t     blue:   RGB_T_BIT_DEPTH;
} rgb_t;

int main(void)
{
        printf("sizeof( rgb_t ) = %d\n", sizeof( rgb_t ));
        return 0;
}


By default, structs are not packed. That is, data types with at least the required number of bits are used. The reason is that the code generated for packed structs is slow.

Code:
$ gcc -Wall -o pack pack.c
$ ./pack
sizeof( rgb_t ) = 4
$ gcc -Wall -o pack pack.c -fpack-struct
$ ./pack
sizeof( rgb_t ) = 2
$


Notice that you need to tell the compiler to pack the struct with the -fpack-struct command line option.

sajiimori wrote:
C does support bitfields, but they're not very fast on GCC and they aren't guaranteed to have any particular arrangement...

It is true that they are not guaranteed to have any particular arrangement. I would test every packed structure data type before using it, but in practice I have found that GCC does not muck with the arrangement.

sajiimori wrote:
I'd suggest using plain shifts --

I agree.

-Brendan

#20935 - TheMikaus - Thu May 20, 2004 6:07 am

Actually they do go in a specific order. At least with the dev kit I've got.

Code:
typedef struct tagSprited
{
    //at0
    unsigned y : 8;

    unsigned rotation : 1;
    unsigned DoubleSize : 1;
    unsigned translucent : 1;
    unsigned windowed : 1;
    unsigned mosaic : 1;
    unsigned color_256 : 1;
    unsigned tall : 1;
    unsigned wide : 1;

    //at1
    unsigned x : 9;
    unsigned rotation_index : 3;
    unsigned hflip : 1;
    unsigned vflip : 1;
    unsigned spriteSize:2;
   
    //at2
    unsigned name : 10;
    unsigned priority : 2;
    unsigned pallette : 4;
   
    unsigned short at3;
   
} mSprite;

That's what I use for mine. Some of the fields might be a bit off (in length) I don't use it that often, but I use it for the one game I'm doing now. Works fine.

#20943 - f(DarkAngel) - Thu May 20, 2004 12:05 pm

The memory addressing unit is bytes, and there's no actual instruction for working on bits, as far i know.

So what is the code generated for this? Bitmasking? (maybe through bic, and) If yes, this'll be a serious sacrifice of speed for size....
_________________
death scream...


Last edited by f(DarkAngel) on Thu May 20, 2004 6:29 pm; edited 1 time in total

#20950 - torne - Thu May 20, 2004 2:57 pm

It generates bit masking code which is pretty damn slow. Also, the fact that it packs them in some specific order at the moment doesn't mean it will do so in the future; the standard does not guarantee anything, so gcc is free to do whatever it likes.