Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [A5/OSX] al_load_bitmap_f refuses to load .bmp

Credits go to Evert and Matthew Leverton for helping out!
This thread is locked; no one can reply to it. rss feed Print
[A5/OSX] al_load_bitmap_f refuses to load .bmp
X-G
Member #856
December 2000
avatar

The title says it all. I have a chunk of memory that is an exact copy of a .bmp file from disk. I have a file interface that reads from memory as appropriate. This interface does load this .bmp correctly on Windows. This file interface also loads .pcx files correctly on both Windows and OSX. It does not load .bmp on OSX, just returning NULL and leaving nothing in Allegro's errno, which means I have no indication what is wrong.

Suggestions? This is kinda urgent.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Evert
Member #794
November 2000
avatar

Check whether the .bmp is loaded by the native image loader or using Allegro's loader (the log file should tell you what formats the native image loader is taking care of). If it is the native loader, try disabling it (which means you don't get .png or .jpg support without libpng and libjpg).
You may want to do the same on Windows.

Allegro has a bmp loader (addons/image/bmp.c), but Windows and OS X both have native loaders as well that use OS calls. The problem could be with any of these (are there bmp formats that Windows supports but Allegro's native loader and/or OS X does not?) and the first thing to do is to check which of them is actually being used.

X-G
Member #856
December 2000
avatar

What log file? Where is this located? How do I disable the native loader?

EDIT: It is using the native loader. How do I disable it?

EDIT2: It works without hte native loader.

EDIT3: Similar problem with Ogg. This time errno is sometimes 12, sometimes 21. This has not been tested on Windows. What the fuck does "12" mean? The error codes aren't listed anywhere!

EDIT4: If it's just errno, then 12 = ENOMEM. Which makes no fucking sense! Help? What is even setting this, I'm not seeing any calls to al_set_errno in acodec.

EDIT5: It's not even calling any of my file IO functions! I added logging to my custom fread(), and nothing is logged for the OGGs. What is going on here?

EDIT6: Forget it, something else was setting errno to 12. It doesn't touch errno at all. But it sitll doesn't call any of my I/O functions!

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Dizzy Egg
Member #10,824
March 2009
avatar

How about increasing the MaxDsiz kernel parameter to 64?

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

X-G
Member #856
December 2000
avatar

Dizzy Egg said:

How about increasing the MaxDsiz kernel parameter to 64?

I don't know what that is or why it is relevant. Also see EDIT6. ENOMEM is a red herring.

As far as I can tell now it's just stubbornly refusing to load. Yes, I compiled with Vorbis. But it's calling none of my IO stuff, it just returns NULL.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Matthew Leverton
Supreme Loser
January 1999
avatar

X-G, some of the loaders use fseek(0) (etc) and are not sequential. Are you trying to load a data chunk that doesn't start at position 0 within a file? If so, you have two options:

  1. Read the entire sub chunk into memory first, then call memopen on it, then load it.

  2. Ask for my file slice code, which sits on top of any custom file interface and resets the seeking boundaries.

That wouldn't explain why your interface isn't being touched though...

X-G
Member #856
December 2000
avatar

some of the loaders use fseek(0) (etc) and are not sequential. Are you trying to load a data chunk that doesn't start at position 0 within a file

It is not reading directly from a file at all. This is from a chunk of (encrypted) memory through a set of I/O hooks I wrote myself that do automatic decryption. But my I/O functions aren't getting called at all. I know the functions work otherwise, because they are used for BMP loading which, at this point, works just fine. Seeking etc. works fine in all directions. But my fseek doesn't called, or any other f* functions of mine.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Matthew Leverton
Supreme Loser
January 1999
avatar

I haven't looked at the OS X code... is it even programmed to run the native file loaders through the custom file interface? Of course, this wouldn't apply to the OGG file.

I wrote the native GDI+ for Windows, and I know that one uses custom interfaces.

I would check that the fp->vtable (or something like that) is actually set to the proper interface. If so, then it would seem to be a bug with Allegro if none of your read or seek functions are called.

X-G
Member #856
December 2000
avatar

I would check that the fp->vtable (or something like that) is actually set to the proper interface.

It is. I create the file handle myself and do all the initialization manually, such as setting the vtable. The only NULL entries are for fopen, fclose and fwrite. And, as I said, it works for the BMP loader. I don't think there is a native OGG interface for OSX... is there? It definitely wanted to link with libvorbis and libogg.

The code I use is simple:

#SelectExpand
1ALLEGRO_FILE* wrapDaxBlock(const unsigned char* pMemory, size_t uiSize) { 2 DAX_FILE* fp = malloc(sizeof(DAX_FILE)); 3 memset(fp, 0, sizeof(DAX_FILE)); 4 5 fp->al.vtable = &gDaxVTable; 6 fp->pMemory = pMemory; 7 fp->uiMemorySize = uiSize; 8 fp->uiCursor = 0; 9 fp->uiIsEOF = 0; 10 11 return (ALLEGRO_FILE*)fp; 12} 13 14 15... 16 17 ALLEGRO_FILE* pDaxFile = wrapDaxBlock(pMemory, uiMemorySize); 18 ALLEGRO_SAMPLE* pSample = al_load_sample_f(pDaxFile, ext);

APPEND: The only other option I can think of is if it bails out before even attempting to do any I/O. How would I find out?

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Matthew Leverton
Supreme Loser
January 1999
avatar

X-G said:

I don't think there is a native OGG interface for OSX... is there?

Not that I know of. Can you load an ogg file from a regular file using stdio? (Are you positive you've initialized that addon, etc?)

Your code looks correct. Just an FYI: 5.1 / 5.0RC4 will be slightly different in how you initialize a custom interface, as it no longer requires access to the internals.

Evert
Member #794
November 2000
avatar

X-G said:

What log file? Where is this located? How do I disable the native loader?

Sorry, my bad. I assumed you were using the debug version. I guess you found the options in the end, but just in case: you can set all of those from the cmake GUI.

Quote:

EDIT2: It works without hte native loader.

Ok.
There is the following block of code in addons/image/macosx.m:

      /* Unload previous loader, if any */
      al_register_bitmap_loader(s, NULL);
      al_register_bitmap_loader_f(s, NULL);

Disable that and it should only use the native loader for formats it didn't previously understand (like png and jpg) and otherwise use the default loader. Which may actually be the preferred behaviour.

is it even programmed to run the native file loaders through the custom file interface?

It should do; it uses al_fopen() and friends.

X-G
Member #856
December 2000
avatar

Can you load an ogg file from a regular file using stdio?

Quick and dirty test says no. Sigh. Here's what I do:

  if (al_install_audio() && al_init_acodec_addon())
  {
    al_reserve_samples(16);
    LOGWRITE("Sound OK");
    return 0;
  }

It logs that and returns zero.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Thomas Fjellstrom
Member #476
June 2000
avatar

Evert said:

It should do; it uses al_fopen() and friends.

If you don't set the current file interface to your custom one, then it won't ever use it. Going on the only code posted, it seems X-G is making a plain wrapped memfile like interface, so it shouldn't be an issue.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Matthew Leverton
Supreme Loser
January 1999
avatar

X-G said:

Quick and dirty test says no

I'd check to make sure the ogg loader is being registered. It might show up in a debug log file. Otherwise, step-by-step debugging should tell you that.

X-G
Member #856
December 2000
avatar

Now I'm confused and annoyed. To find out if OGG was being registered correctly, I added a call to ALLEGRO_INFO in acodec.c to see if it was being called. Built Allegro.

AND NOW LOADING GODDAMN WORKS. WHAT.

I still can't hear anything, but loading works. It calls my function and results in a sample being returned.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Matthew Leverton
Supreme Loser
January 1999
avatar

Did you get anything figured out?

X-G said:

The only NULL entries are for fopen, fclose and fwrite.

By the way, I think fopen is the only one that is allowed to be NULL. The others will crash if somebody tries to use them, so they should at least have NOP stubs in your interface.

In 5.0RC3, your fclose is responsible for freeing the file pointer. In future versions, it will instead be responsible for freeing the userdata pointer (which will be pointing to your custom struct), while Allegro will free the file pointer itself.

X-G
Member #856
December 2000
avatar

I didn't figure it out, it just suddenly started working for no reason. I didn't change any logic. And right now (as well as yesterday), my priorities are not on figuring out why it's behaving this way, but rather to just get it working.

Today's challenge: figure out why the audio isn't playing. :P

Anyway, the way I'm using this now, writing and closing the file should never occur. The load_*_f functions don't close the file, I manually construct the file, and they have no reason to write to the file, so I should be safe. Right?

I think we're about done for this thread. Thanks.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Matthew Leverton
Supreme Loser
January 1999
avatar

If you don't call those functions, then it's okay. I suppose you are calling free directly on pDaxFile, which will work up to 5.0RC3.

But the next release will clean things up a bit such that you don't need to access the internals. Each ALLEGRO_FILE will contain a userdata pointer. In your case, that will point to a DAX_FILE (which no longer will contain the ALLEGRO_FILE at the beginning).

So you'll need to call al_fclose() to free the userdata memory. Then Allegro will destroy the ALLEGRO_FILE* itself.

Something like:

#SelectExpand
1ALLEGRO_FILE* wrapDaxBlock(const unsigned char* pMemory, size_t uiSize) { 2 DAX_FILE* fp = malloc(sizeof(DAX_FILE)); 3 memset(fp, 0, sizeof(DAX_FILE)); 4 5 fp->pMemory = pMemory; 6 fp->uiMemorySize = uiSize; 7 fp->uiCursor = 0; 8 fp->uiIsEOF = 0; 9 10 return al_create_file_handle(&gDaxVTable, fp); 11} 12 13void closeDaxBlock(const ALLEGRO_FILE *f) { 14 free(al_get_file_userdata(f)); 15} 16 17fp = wrapDaxBlock( ... ); 18... 19al_fclose(fp);

Edit: fixed the al_free() to al_fclose().

X-G
Member #856
December 2000
avatar

Makes sense. I'll keep that in mind.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Go to: