I did some research and experimentation and I found out how to use the built in Auto Power Down (APD) feature in an assembly program. I couldn't really find any kind of relevant documentation on WikiTi so I just looked at the memory areas that looked related and tried some things until I got something that works. Since I found this all out by experimentation, there is a chance that I could be totally wrong and that the calc doesn't go into low power mode or something but I'm pretty sure that I am correct. I guess the only way to tell for sure is for me to stick fresh batteries in a calc and run it in an assembly program until it dies and then to do the same thing for my APD but that could take weeks to a month.
The routiene in Axe (but it is very easy to translate to assembly if you want):
:GOff() ;If you are using graylib or any custom interrupt, turn it off here. If not, skip this step
:*save 0x8000* ;The APD destroys 256 bytes starting at 0x8000 so if you use that area for storage, you will need to back it up. If not, you don't have to do anything.
:0x180C->{0x89F8}r ;Set some flags so that it works
:0x0101->(0x8448)r ;Set the APD timer to right about to shut off
:Asm(FF) ;Call the OS interrupt (This is 'rst 38h' in assembly)
:FnOn ;Interrupts should be on at this point because of the last line but it doesn't hurt to be very sure. (This is 'ei' in assembly)
:Stop ;Wait until the OS interrupt fires. It is at this point that the calc actually turns off (This is 'halt' in assembly)
:0x7469->{0x8448}r ;Set the APD timer to what it normally is so the calc doesn't instantly APD when you quit the program
:0x0804->{0x89F8}r ;Restore some flags
:*restore 0x8000* ;Restore the values you saved. If you didn't save anything you of course don't need to restore it
:GOn() ;If you are using graylib or any custom interrupt, turn it back on here
This routiene turns the calc off as soon as you call it which means if you want your program to turn off after no keys have been pressed for a while, you will have to do that yourself. It works fine if the On key is being held when it starts (which means if you have the user press On to turn the calc off you don't have to wait for them to release On to call this) It doesn't wait for the On key to be released when it is finished so I would put a loop at the end of it to wait until the On key is released.
In my experiments with this it worked fine with all sorts of memory screwed up so as long as you save 0x8000 then you shouldn't have to do any other kind of setup. I don't know exactly what flags I am messing with (since I am too lazy to look up what they are - something like iy + onflags I think) in the two flags steps but I know they are nessicary and that there doesn't seem to be any kind of ill effect from setting them in that way.