I have a system which expects a little endian 16-bit color value with three colors of 5 bit each and one alpha bit.
In big endian it looks like this:
R:{00000-11111} G:{00000-11111} B:{00000-11111} A:{0-1}
I tried to model that with
typedef union {
struct {
SceUChar8 R;
SceUChar8 G;
SceUChar8 B;
SceUChar8 A;
} components;
SceUInt32 Value;
} mgpColor8888;
typedef union {
struct {
SceUChar8 R: 5;
SceUChar8 G: 5;
SceUChar8 B: 5;
SceUChar8 A: 1;
} components;
SceUShort16 Value;
} mgpColor5555;
But the mgp5555 is somehow bugged as a I need the union to create a 16-bit type.
typedef union {
struct {
>>5 bits<< R: 5;
>>5 bits<< G: 5;
>>5 bits <<B: 5;
>>1 bits << A: 1;
} components;
SceUShort16 Value;
} mgpColor5555;
I've hit a brick wall.
The code blow works since I set up the 16-bit value manually instead of using unions like I want to:
SceUShort16 gen5551( SceUChar8 R, SceUChar8 G, SceUChar8 B, SceUChar8 A) {
mgpColor5555 val;
R >>=3;
G >>=3;
B >>=3;
A= (A >= 0x80) ? 0b01 : 0b00;
SceUShort16 temp = ((A & 1) << 15) |((B & 0x1F) <<10 ) | ((G & 0x1F) << 5)| (R & 0x1F);
val.Value = temp;
return val.Value;
}
Why isn't union mgpColor5555
above working?
How do I fix this 5-bit boundary based union in C?
Bit fields are not portable. Use bit operations. Write your own wrappers, setters and getters, for accessing the 5-bit fields you want to get.
I would do something along:
struct { uint8_t R, G, B, A; } mgpColor8888;
struct { uint8_t R :5, G :5, B :5, A :1; } mgpColor5555;
#define mgpColor5555_INIT(R, G, B, A) (struct mgpColor5555){ \
R>>3, G>>3, B>>3, A>=0x80 }
uint16_t mgpColor5555_to_16(const struct mgpColor5555 *t) {
return ((t->A & 1) << 15) |((t->B & 0x1F) <<10 ) | ((t->G & 0x1F) << 5)| (t->R & 0x1F);
}