1; 2; Oliver Schmidt, 2009-09-15 3; 4; Startup code for cc65 (Apple2 version) 5; 6 7 .export _exit, done, return 8 .export __STARTUP__ : absolute = 1 ; Mark as startup 9 10 .import initlib, donelib 11 .import zerobss, callmain 12 .import __ONCE_LOAD__, __ONCE_SIZE__ ; Linker generated 13 .import __LC_START__, __LC_LAST__ ; Linker generated 14 15 .include "zeropage.inc" 16 .include "apple2.inc" 17 18; ------------------------------------------------------------------------ 19 20 .segment "STARTUP" 21 22 ; ProDOS TechRefMan, chapter 5.2.1: 23 ; "For maximum interrupt efficiency, a system program should not 24 ; use more than the upper 3/4 of the stack." 25 ldx #$FF 26 txs ; Init stack pointer 27 28 ; Save space by putting some of the start-up code in the ONCE segment, 29 ; which can be re-used by the BSS segment, the heap and the C stack. 30 jsr init 31 32 ; Clear the BSS data. 33 jsr zerobss 34 35 ; Push the command-line arguments; and, call main(). 36 jsr callmain 37 38 ; Avoid a re-entrance of donelib. This is also the exit() entry. 39_exit: ldx #<exit 40 lda #>exit 41 jsr reset ; Setup RESET vector 42 43 ; Switch in ROM, in case it wasn't already switched in by a RESET. 44 bit $C082 45 46 ; Call the module destructors. 47 jsr donelib 48 49 ; Restore the original RESET vector. 50exit: ldx #$02 51: lda rvsave,x 52 sta SOFTEV,x 53 dex 54 bpl :- 55 56 ; Copy back the zero-page stuff. 57 ldx #zpspace-1 58: lda zpsave,x 59 sta sp,x 60 dex 61 bpl :- 62 63 ; ProDOS TechRefMan, chapter 5.2.1: 64 ; "System programs should set the stack pointer to $FF at the 65 ; warm-start entry point." 66 ldx #$FF 67 txs ; Re-init stack pointer 68 69 ; We're done 70 jmp done 71 72; ------------------------------------------------------------------------ 73 74 .segment "ONCE" 75 76 ; Save the zero-page locations that we need. 77init: ldx #zpspace-1 78: lda sp,x 79 sta zpsave,x 80 dex 81 bpl :- 82 83 ; Save the original RESET vector. 84 ldx #$02 85: lda SOFTEV,x 86 sta rvsave,x 87 dex 88 bpl :- 89 90 ; Check for ProDOS. 91 ldy $BF00 ; MLI call entry point 92 cpy #$4C ; Is MLI present? (JMP opcode) 93 bne basic 94 95 ; Check the ProDOS system bit map. 96 lda $BF6F ; Protection for pages $B8 - $BF 97 cmp #%00000001 ; Exactly system global page is protected 98 bne basic 99 100 ; No BASIC.SYSTEM; so, quit to the ProDOS dispatcher instead. 101 lda #<quit 102 ldx #>quit 103 sta done+1 104 stx done+2 105 106 ; No BASIC.SYSTEM; so, use the addr of the ProDOS system global page. 107 lda #<$BF00 108 ldx #>$BF00 109 bne :+ ; Branch always 110 111 ; Get the highest available mem addr from the BASIC interpreter. 112basic: lda HIMEM 113 ldx HIMEM+1 114 115 ; Set up the C stack. 116: sta sp 117 stx sp+1 118 119 ; ProDOS TechRefMan, chapter 5.3.5: 120 ; "Your system program should place in the RESET vector the 121 ; address of a routine that ... closes the files." 122 ldx #<_exit 123 lda #>_exit 124 jsr reset ; Setup RESET vector 125 126 ; Call the module constructors. 127 jsr initlib 128 129 ; Switch in LC bank 2 for W/O. 130 bit $C081 131 bit $C081 132 133 ; Set the source start address. 134 ; Aka __LC_LOAD__ iff segment LC exists. 135 lda #<(__ONCE_LOAD__ + __ONCE_SIZE__) 136 ldy #>(__ONCE_LOAD__ + __ONCE_SIZE__) 137 sta $9B 138 sty $9C 139 140 ; Set the source last address. 141 ; Aka __LC_LOAD__ + __LC_SIZE__ iff segment LC exists. 142 lda #<((__ONCE_LOAD__ + __ONCE_SIZE__) + (__LC_LAST__ - __LC_START__)) 143 ldy #>((__ONCE_LOAD__ + __ONCE_SIZE__) + (__LC_LAST__ - __LC_START__)) 144 sta $96 145 sty $97 146 147 ; Set the destination last address. 148 ; Aka __LC_RUN__ + __LC_SIZE__ iff segment LC exists. 149 lda #<__LC_LAST__ 150 ldy #>__LC_LAST__ 151 sta $94 152 sty $95 153 154 ; Call into Applesoft Block Transfer Up -- which handles zero- 155 ; sized blocks well -- to move the content of the LC memory area. 156 jsr $D39A ; BLTU2 157 158 ; Switch in LC bank 2 for R/O and return. 159 bit $C080 160 rts 161 162; ------------------------------------------------------------------------ 163 164 .code 165 166 ; Set up the RESET vector. 167reset: stx SOFTEV 168 sta SOFTEV+1 169 eor #$A5 170 sta PWREDUP 171return: rts 172 173 ; Quit to the ProDOS dispatcher. 174quit: jsr $BF00 ; MLI call entry point 175 .byte $65 ; Quit 176 .word q_param 177 178; ------------------------------------------------------------------------ 179 180 .rodata 181 182 ; MLI parameter list for quit 183q_param:.byte $04 ; param_count 184 .byte $00 ; quit_type 185 .word $0000 ; reserved 186 .byte $00 ; reserved 187 .word $0000 ; reserved 188 189; ------------------------------------------------------------------------ 190 191 .data 192 193 ; Final jump when we're done 194done: jmp DOSWARM ; Potentially patched at runtime 195 196; ------------------------------------------------------------------------ 197 198 .segment "INIT" 199 200zpsave: .res zpspace 201rvsave: .res 3 202