I think cutting down on sprite frames is the only way it'd work in regular system RAM... but then we're limiting the game's appearance, and one of lord_cack's driving points of this game is to have a lot of animation.
Since there are so many frames of sprite animation, each new frame a sprite has is loaded in realtime into VRAM with a load_vram() call. Each enemy has its own unique area in VRAM where its frames get loaded into. There's too many frames to load everything into VRAM at once and just change the sprite's pattern pointer. Of course, that means that all the sprite frames have to be kept in system RAM, which eats up space pretty quickly. The ADPCM RAM is mostly used for sound effects already so that option is out. Also, I used ADPCM RAM to VRAM transfers for some of MSR's cutscenes and the speed is atrocious.
Unfortunately, the project already is pretty well organized; I literally spent weeks ahead of the demo show making sure things could fit properly and nothing was wasted. The current scheme for sprite frames is about as efficient as it gets, I've got VRAM mapped out to the byte, and this project is why I went into pceas's code and modified it to send the proc size list to stdout... that allowed me to go into JB's code and do function shuffling until everything fit neatly with minimal space waste since pceas doesn't do this automatically, nor does it allow procs to cross bank boundaries. At this point, the only thing that would really help is to start converting finalized functions to inline assembly... but since we're already short on memory and we still have things to add, downsizing the code would just give more space to fill the void with more graphics, so we'll soon be right back where we were before... a slightly more functional game. Might not be worth it to do things that way since we have the ACD to utilize, which removes 95% of these problems.