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