[A89] Problem w/ BITMAP (TI-SDK)


[Prev][Next][Index][Thread]

[A89] Problem w/ BITMAP (TI-SDK)




> I'm using the TI SDK beta1, and am trying to put a bitmap (74 rows x 158
cols) on the screen.  However, It's throwing an error (too many initializers
at {level 2}) at the first five bytes of the bmp after the rows, cols:
>
>                                             These five
> BITMAP world = {74,158,{0xFF,0xFF,0xFF,0xFF,0xFF.....}};
>
> What's going on?

This problem is due to one of C's few (IMHO) shortcomings.

A bitmap, im memory, is stored as the following:

One WORD: height
One WORD: width
ARRAY of BYTES: bitmap data

The problem is knowing the length of the final array.  For each bitmap, it
wil be different, depending on the width and height of that specific bitmap.

But TI needed to define a BITMAP struct.  Ideally, it would look like this,
but this code is syntactically incorrect in ANSI C:

/* this will not compile */
typedef struct
 {
    unsigned short height;
    unsigned short width;
    unsigned char data[height*((width+7)%8)];
 } BITMAP, *pBITMAP;

But that code is not valid because the size of the data array must be
constant in ANSI C.  In other words, ANSI C does not allow us to have a
struct that ends in a variable size array (some compilers, like GCC, add
their own extensions that allow this).  So TI, when defining the BITMAP
struct, wrote something like this (see tiams.h for the actual definition);

typedef struct
 {
    unsigned short height;
    unsigned short width;
    unsigned char data[1];
 } BITMAP, *pBITMAP;

That code works for the most important purpose -- passing the address of a
bitmap into a function -- but isn't very useful for declaring a bitmap,
since it will only let the bitmap be one byte long.


There are a few ways to work around this.  Niklas replied with one solution,
defining another bitmap type with the correct array size for each size
bitmap.  I created another workaround, which I find much more useful when
you have many bitmap sizes:

unsigned char blockData[] =
 {
    0, 9,            // null byte, then height
    0, 21,           // another null, then width.  Data follows:
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
 };
BITMAP* block = (BITMAP*)blockData;

(Aside: I think that could be made into a macro, but I'm not too good with
macros in C.  If anyone (Zeljko?) could write a macro to make that a bit
easier, I'd appreciate it =)

Hopefully, the reason why that works is pretty clear.  First it creates an
array of bytes containing the raw data, then makes a pointer to a bitmap
that points to all of the data.


Ideally, this code could use const's as follows, but I believe a bug in the
SDK compiler causes it to fail if you try to declare more than one constant
bitmap:

/* this will compile, but may crash using the SDK)
const unsigned char blockData[] =
 {
    0, 9,            // null byte, then height
    0, 21,           // another null, then width.  Data follows:
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
 };
const BITMAP* const block = (const BITMAP* const)blockData;

As you can see, I like const's, but for some odd reason any program compiled
with the SDK crashes if more than one bitmap is declared in this manner.  If
anyone knows the explanation for this, please let me know.  But for now,
just do it without the const's, and accept that the SDK compiler isn't meant
to optimize anything =)

    -Scott





Follow-Ups: