OK, well, you shouldn't really be doing this these days, but it is fun
If you really want to make your own startup-code, do this:
1) Store the current view and coplist from graphicsbase (offsets 34 and 38 ;-) ).
2) Call LoadView() with nothing in A1. This removes the intuition display, and will switch out Picasso96 screens etc.
3) Do two "WaitTOF()"s. This allows enough time for interlaced displays to be turned off
4) Call "OwnBlitter()" and "WaitBlit()" to take over control of the blitter safely
5) Call Forbid() to turn off multitasking
6) Store DMACONR, INTENAR, INREQR and ADKCONR, or'd with $8000 for later
7) Put $7fff into DMACON, INTENA and ADKCON to turn off all DMA an interrupts
Load your copperlist into Cop1lc, and write to Copjmp1
9) Set up your interrupts. Remember to use VBR if there is a 68020+ present! Also save any interrupt vectors before you overwrite them
10) Turn on DMA and interrupts you require
To restore the system:
1) Put $7fff into DMACON, INTENA and ADKCON
2) Restore system interrupt pointers
3) Restore copper from gfxbase into cop1lc, and write to copjmp1
4) Move the stored (and $8000 or'd) DMACONR, INTENAR and ADKCONR values into DMACON, INTENA and ADKCON
5) Call LoadView() with the view you stored from graphicbase. This will bring P96 screens back etc.
6) Call DisownBlitter()
7) Call Permit()
Some notes:
* Detect the processor, and use VBR if necessary
* If you use sprites, set the resolution in BPLCON3, since LoadView(NULL) fails to reset it if the user has a hires mousepointer. If BPLCON3 is in your coplist that would cover that anyway.
* Set Intreq twice at the end of interrupts. This is a workaround for 040 & 060 based A4000 systems. For example, a level 6 interrupt should look like:
movem.l d0-d7/a0-a6,-(sp)
lea $dff000,a6
; .... code ....
move.w #$2000,Intreq(a6)
move.w #$2000,Intreq(a6)
movem.l (sp)+,d0-d7/a0-a6
rte
This way your code should gracefully kill and restore the OS on everything from a 256k KS1.x A1000 up to an OS3.9 mediator based A4000 and everything inbetween.