in setupgraphics():
SPRITE_PALETTE_SUB[(n*16)+2] = SPRITE_PALETTE[(n*16)+1];
Should that not be:
SPRITE_PALETTE_SUB[(n*16)+2] = SPRITE_PALETTE[(n*16)+2];
also you are dmaCopying 32x32 pixels, the sprite is 16x32 pixels - you might want to change that and see if it fixes your issue.
---
Since you are using 1 sprite that is the same for all of the objects, what I would do is to pre-allocate the sprite in both sprite vram area's and pass the offset to the balloon init code as a pointer, that way you don't need to allocate a new balloon every time you create one. This will reduce the amount of ram that your using in the sprite VRAM, and also allow for some kind of animation. Look at the simple_animation example for 2 ways to do animation with the current oam* functions.
For example in my current little play around nds project I'm using 2 sprites of 32x32 that are artificially linked togther to animate a 32x40 - 32x64 size sprite, and I've got the following stored in a temporary buffer:

The first 32x32 block is stored in VRAM, and never changes, the other images are dmaCopied only when I change the displayed image.
I've also got the following loaded into VRAM, before the above sprite is loaded:

As you can see I have all the animation frames loaded for the other objects, this is so that different sprites can have a different frame of animation at the time it is displayed (I've not completed the animation frames for the other sprites yet, and at the moment it's just placeholder graphics).
The first way (the dmaCopy every fram change) is good for single sprites, where as the larger image is good if you have multiple sprites all sharing animation frames, but they can have different animation frames shown at the same time.
The large image has 4 placeholder colours - 3 greys (main ship top, main ship engine, bullets) and a purple (boss graphics), for some reason the files are stored with colour 0 being set to transparent, when it should be black.