]> git.sur5r.net Git - cc65/blob - libsrc/apple2/crt0.s
Use well-known location BLTU2 for "memmove()".
[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 the source start address.
32         lda     #<(__ZPSAVE_RUN__ + __INIT_SIZE__)
33         ldy     #>(__ZPSAVE_RUN__ + __INIT_SIZE__)
34         sta     $9B
35         sty     $9C
36
37         ; Set the 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 the destination last address.
44         lda     #<__LC_LAST__
45         ldy     #>__LC_LAST__
46         sta     $94
47         sty     $95
48
49         ; Call into Applesoft Block Transfer Up -- which handles zero-
50         ; sized blocks well -- to move the content of the LC memory area.
51         jsr     $D39A           ; BLTU2
52
53         ; Set the source start address.
54         lda     #<__ZPSAVE_RUN__
55         ldy     #>__ZPSAVE_RUN__
56         sta     $9B
57         sty     $9C
58
59         ; Set the source last address.
60         lda     #<(__ZPSAVE_RUN__ + __INIT_SIZE__)
61         ldy     #>(__ZPSAVE_RUN__ + __INIT_SIZE__)
62         sta     $96
63         sty     $97
64
65         ; Set the 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 Up -- which handles moving
72         ; overlapping blocks upwards well -- to move the INIT segment.
73         jsr     $D39A           ; BLTU2
74
75         ; Delegate all further processing, to keep the STARTUP segment small.
76         jsr     init
77
78         ; Avoid a 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 the 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 that 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 the 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 the ProDOS dispatcher instead.
149         lda     #<quit
150         ldx     #>quit
151         sta     done+1
152         stx     done+2
153
154         ; No BASIC.SYSTEM; so, use the addr of the ProDOS system global page.
155         lda     #<$BF00
156         ldx     #>$BF00
157         bne     :+              ; Branch always
158
159         ; Get the highest available mem addr from the BASIC interpreter.
160 basic:  lda     HIMEM
161         ldx     HIMEM+1
162
163         ; Set up the C stack.
164 :       sta     sp
165         stx     sp+1
166
167         ; Call the module constructors.
168         jsr     initlib
169
170         ; Switch in LC bank 2 for R/O.
171         bit     $C080
172
173         ; Push the command-line arguments; and, call main().
174         jmp     callmain
175
176         .code
177
178         ; Set up the RESET vector.
179 reset:  stx     SOFTEV
180         sta     SOFTEV+1
181         eor     #$A5
182         sta     PWREDUP
183 return: rts
184
185         ; Quit to the ProDOS dispatcher.
186 quit:   jsr     $BF00           ; MLI call entry point
187         .byte   $65             ; Quit
188         .word   q_param
189
190         .rodata
191
192         ; MLI parameter list for quit
193 q_param:.byte   $04             ; param_count
194         .byte   $00             ; quit_type
195         .word   $0000           ; reserved
196         .byte   $00             ; reserved
197         .word   $0000           ; reserved
198
199         .data
200
201         ; Final jump when we're done
202 done:   jmp     DOSWARM         ; Potentially patched at runtime
203
204         .segment        "ZPSAVE"
205
206 zpsave: .res    zpspace
207
208         .bss
209
210 rvsave: .res    3