Why not embed all graphics and audio in dynamically loaded libraries?

One of my favorite new C tricks is linking arbitrary files to a binary using the gcc flags -Wl,–format=binary -Wl,–foo.ext -Wl,–format=default and then accessing the contents with asm(_binary_foo_ext_start).

Since SDL can load most (all?) of its supported graphical and audio structures from memory with the magic of RWops, why not package things together (for example, all the sprites and audio for a level) into a library (eg .dll) and load/free it dynamically just like from file? Of course you’d also have a library for stuff like the player avatar’s assets and such so that you can reduce redundancy and manage the life of those separately.

Advantages I can think of are:

  1. Enforces organization of assets so that you can’t load something when you don’t need it and won’t forget to free something you no longer need.

  2. Turns runtime and logical errors into compile time errors. If you don’t have the file for a spritesheet present, the build of the library will fail at the linker stage rather than letting it succeed only to later fail when it tries to load at runtime. Of course, with dynamically loaded code, you can still forget the whole library, but this should be way easier to catch.

  3. Assets are more tamper-resistent and better hidden. They look like any old dll that most players won’t want to mess with, and there’s no need for encryption! Might still be a good idea though…

  4. Cleaner deliverable. Hundreds of spritesheets? Not anymore! Just a handful of libraries that can fit neatly into a folder in a subdirectory.

But what are some disadvantages to something like this? Would it take more memory or be slower? More prone to break? Let me know what you think!

Advantages I can think of are:

  1. Enforces organization of assets so that you can’t load something when you don’t need it and won’t forget to free something you no longer need.
  2. Turns runtime and logical errors into compile time errors. If you don’t have the file for a spritesheet present, the build of the library will fail at the linker stage rather than letting it succeed only to later fail when it tries to load at runtime. Of course, with dynamically loaded code, you can still forget the whole library, but this should be way easier to catch.
  3. Assets are more tamper-resistent and better hidden. They look like any old dll that most players won’t want to mess with, and there’s no need for encryption! Might still be a good idea though…
  4. Cleaner deliverable. Hundreds of spritesheets? Not anymore! Just a handful of libraries that can fit neatly into a folder in a subdirectory.
  1. I don’t see how this has any bearing whatsoever on how easy it is to forget to free things you no longer need.
  2. This same advantage could be had by setting up a custom build step that examines your asset files and makes sure there are no dangling references. (This is, of course, much easier if you don’t hard-code any asset file names into your game’s codebase.)
  3. You would do well to erase the very concept of “tamper-resistant and better hidden” from your mind entirely. If it’s on someone else’s computer, it is under their control; obfuscation is a fool’s errand and always has been. You don’t have to stop “most players;” you have to beat everybody in the world. Because all it takes is one person, anywhere in the world, to figure out the trick and post an asset extractor tool on the Web, and your data is cracked everywhere forever. The only winning move is not to play.
  4. Many games and game engines deal with this by having some sort of archive file with the assets in it. This is a time-honored tradition dating back at least as far as DOOM, and probably earlier.

Disadvantages:

  1. It looks “clever.” It’s not going to hide your assets. If a game is supposed to have 200 MB of assets, and you can’t find any asset files anywhere, but one of the few files the game ships with is a 200 MB DLL sitting right there in plain sight, it’s going to stand out like a brown smear on a child’s face when one is looking for missing chocolate chip cookies. All this will do is paint a target on your game. Crackers will see this and say “challenge accepted.”
  2. It makes source control messier, especially given the way many source control systems have difficulty dealing with large files.
  3. It makes patching and updates harder if you have to update one huge file when all you actually care about is updating one small asset.
  4. It is actively hostile towards modding. I can’t emphasize enough how important this is. Most games get played once or twice and then forgotten. Some stick around on the strength of a powerful story. (The Final Fantasy series, the Mass Effect games, etc.) A very few have massive replay value due to the importance of skill in gameplay. (Tetris, Super Mario Bros, etc.) But some of the most enduring gems, ones that stick around for decades with strong, active communities, are the ones that people keep doing things with because they’re extensible. Neverwinter Nights. The Elder Scrolls series. Heck, people are still actively creating new DOOM content, simply because they can! A wise game designer will work to encourage moddability in their games, rather than impede it.

Thanks for the reply; you bring up some good points. Freeing assets becomes easier because remember, it’s wrapped in a library, which can still contain the code to load everything at once and free everything at once.