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