]> git.sur5r.net Git - cc65/blob - libsrc/apple2/crt0.s
Startup code with interruptor support by Oliver Schmidt
[cc65] / libsrc / apple2 / crt0.s
1 ;
2 ; Startup code for cc65 (Apple2 version)
3 ;
4 ; This must be the *first* file on the linker command line
5 ;
6
7         .export         _exit, __Exit
8         .import         zerobss
9         .import         initlib, donelib
10         .import         callmain, callirq
11         .import         __STARTUP_LOAD__, __BSS_LOAD__  ; Linker generated
12         .import         __INTERRUPTOR_COUNT__           ; Linker generated
13
14         .include        "zeropage.inc"
15         .include        "apple2.inc"
16         .include        "mli.inc"
17
18 ; ------------------------------------------------------------------------
19
20         .segment        "EXEHDR"
21
22         .addr           __STARTUP_LOAD__                ; Start address
23         .word           __BSS_LOAD__ - __STARTUP_LOAD__ ; Size
24
25 ; ------------------------------------------------------------------------
26
27         .segment        "STARTUP"
28
29         ; ProDOS TechRefMan, chapter 5.2.1:
30         ; "For maximum interrupt efficiency, a system program should not
31         ;  use more than the upper 3/4 of the stack."
32         ldx     #$FF
33         txs                     ; Init stack pointer
34
35         ; Delegate all further processing to keep STARTUP small
36         jsr     init
37
38         ; Avoid 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         ; Check for valid interrrupt vector table entry number
44         lda     intnum
45         beq     :+
46
47         ; Deallocate interrupt vector table entry
48         dec     params          ; Adjust parameter count
49         jsr     ENTRY
50         .byte   $41             ; Dealloc interrupt
51         .addr   params
52
53         ; Call module destructors
54 :       jsr     donelib
55
56         ; Restore the original RESET vector. This is also the __Exit entry
57 __Exit: ldx     #$02
58 :       lda     rvsave,x
59         sta     SOFTEV,x
60         dex
61         bpl     :-
62
63         ; Copy back the zero page stuff
64         ldx     #zpspace-1
65 :       lda     zpsave,x
66         sta     sp,x
67         dex
68         bpl     :-
69
70         ; ProDOS TechRefMan, chapter 5.2.1:
71         ; "System programs should set the stack pointer to $FF at the
72         ;  warm-start entry point."
73         ldx     #$FF
74         txs                     ; Re-init stack pointer
75
76         ; Back to DOS
77         jmp     DOSWARM
78
79 ; ------------------------------------------------------------------------
80
81         .segment        "INIT"
82
83         ; Save the zero page locations we need
84 init:   ldx     #zpspace-1
85 :       lda     sp,x
86         sta     zpsave,x
87         dex
88         bpl     :-
89
90         ; Save the original RESET vector
91         ldx     #$02
92 :       lda     SOFTEV,x
93         sta     rvsave,x
94         dex
95         bpl     :-
96
97         ; ProDOS TechRefMan, chapter 5.3.5:
98         ; "Your system program should place in the RESET vector the
99         ;  address of a routine that ... closes the files."
100         ldx     #<_exit
101         lda     #>_exit
102         jsr     reset           ; Setup RESET vector
103
104         ; Clear the BSS data
105         jsr     zerobss
106
107         ; Setup the stack
108         lda     HIMEM
109         sta     sp
110         lda     HIMEM+1
111         sta     sp+1            ; Set argument stack ptr
112
113         ; Call module constructors
114         jsr     initlib
115
116         ; Check for interruptors
117         lda     #<__INTERRUPTOR_COUNT__
118         beq     :+
119
120         ; Check for ProDOS
121         lda     ENTRY
122         cmp     #$4C            ; Is MLI present? (JMP opcode)
123         bne     :+
124
125         ; Allocate interrupt vector table entry
126         jsr     ENTRY
127         .byte   $40             ; Alloc interrupt
128         .addr   params
129
130         ; Push arguments and call main()
131 :       jmp     callmain
132
133 ; ------------------------------------------------------------------------
134
135         .segment        "LOWCODE"
136
137         ; ProDOS TechRefMan, chapter 6.2:
138         ; "Each installed routine must begin with a CLD instruction"
139 intrpt: cld
140
141         ; Call interruptors
142         jsr     callirq
143
144         ; ProDOS TechRefMan, chapter 6.2:
145         ; "When the routine that can process the interrupt is called, it
146         ;  should ... return (via an RTS) with the carry flag clear."
147         clc
148         rts
149
150 ; ------------------------------------------------------------------------
151
152         .code
153
154         ; Setup RESET vector
155 reset:  stx     SOFTEV
156         sta     SOFTEV+1
157         eor     #$A5
158         sta     PWREDUP
159         rts
160
161 ; ------------------------------------------------------------------------
162
163         .data
164
165 zpsave: .res    zpspace
166
167 rvsave: .res    3
168
169 params: .byte   $02             ; Parameter count
170 intnum: .byte   $00             ; Interrupt number
171         .addr   intrpt          ; Interrupt handler