Retrieving the real color depth

Did you ever need to find out from your Windows application, on what color depth it's running? If yes, you will probably have used something like

bpp = GetDeviceCaps(GetDC(NULL), BITSPIXEL);


But what about 16 bpp vs 15 bpp? MSDN says in both cases 16 is returned. So this function isn't useful to get the real color depth. It's a little more complicated. Here's a function that allows you to get the real color depth. Based on SDL code, Copyright (C) 1997-2006 Sam Lantinga.


ULONG
GetRealColorDepth()
{
HBITMAP hbmp;
HDC hdc;
struct
{
BITMAPINFOHEADER bmiHeader;
ULONG aulMasks[3];
} bmi;
PBITMAPINFO pbmi = (PBITMAPINFO)&bmi;
ULONG ulColorDepth;

/* Get the screen DC */
hdc = GetDC(NULL);

/* Create a compatible bitmap */
hbmp = CreateCompatibleBitmap(hdc, 1, 1);

/* Fill BITMAPINFOHEADER */
memset(&bmi, 0, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
GetDIBits(hdc, hbmp, 0, 1, NULL, pbmi, DIB_RGB_COLORS);

/* Get the basic color depth */
ulColorDepth = bmi.bmiHeader.biBitCount;

/* Special case 16 bpp */
if (ulColorDepth == 16)
{
/* Call again to fill in the bitfields */
GetDIBits(hdc, hbmp, 0, 1, NULL, pbmi, DIB_RGB_COLORS);

/* Check the red mask */
if (bmi.aulMasks[0] == 0x7c00)
ulColorDepth = 15;
}

/* Cleanup and return */
DeleteObject(hbmp);
return ulColorDepth;
}

Operands in gcc inline assembly

Some time ago I was struggling with gcc's inline assembly. I wanted to use the address of a function. "m" as a constraint didn't work. gcc said it's not directly addresseble. "i" worked, but not with "lea". In this case the assembler complained about invalid operand. No wonder, it produced something like "lea $function, %%eax". I read in the gcc manual. Nothing that helped me. I tried all constraints. It just didn't work. And now I found it. Not inthe gcc manual, but on another webpage (A Brief Tutorial on GCC inline asm (x86 biased)), when I was seeking something completely different.

The solution is to modify the way gcc translates the operands into strings. Where "%0" will give you the default represenstation of operand 0, you can modify it, by inserting a letter (like "%c0"). The ones that were accepted by gcc are: a,b,c,d,e,f,h,k,l,n,q,s,t,w,x,y,z, A,B,C,D,E,F,H,L,O,P,Q,S,T,W,X,Y. Some of them did nothing (d, X) others resulted in a compiler error (e, f, C, D, E, F, H). This is the rest:

  • %a0 - memory addressed by register operand 0
  • %A0 - operand 0 with a "*" prefix
  • %b0 - 8bit form of register operand 0 (al)
  • %B0 - gives "b"
  • %c0 - operand 0, without $ prefix
  • %h0 - high 8 bit form of register operand 0 (ah)
  • %k0 - 32bit form of register operand 0 (eax)
  • %l0 - operand 0 as label
  • %L0 - gives "l"
  • %n0 - negate operand 0 without $ prefix
  • %O0 - nothing
  • %P0 - same as %c0
  • %q0 - 64bit form of register operand 0 (rax)
  • %Q0 - gives "l"
  • %s0 - operand 0 with a comma appended
  • %S0 - gives "s"
  • %t0 - only usable on immediate operands, does nothing?
  • %T0 - gives "t"
  • %w0 - 16 bit form of register operand 0 (ax)
  • %W0 - gives "w"
  • %x0 - same as %w0
  • %y0 - same as %k0
  • %z0 - Opcode suffix based on operand 0 size (b, w, l), example asm ("mov%z1 %1, %0" : "=r"(ret) : "r"(val));

enabling msvc specific stuff in gcc

Just as note to myself (so I don't have to search all those ros-arm-bringup commits again to find it): the -fms-extensions gcc compiler switch: It enables such things like anonymous structs/unions:

typedef struct
{
int a;
int b;
} STRUCT1;

struct
{
STRUCT1;
int anotherone;
} x;

First post

Hmm, ready. Kinda. Looks like I need to write some stuff now.....

Damn, I knew there was a catch. This is probably going to be work and stealing my time. Well let's see where this is going.