]> git.sur5r.net Git - cc65/blob - libsrc/c64/crt0.s
a513b1f7380b42df1cc942cd26e2817479520e36
[cc65] / libsrc / c64 / crt0.s
1 ;
2 ; Startup code for cc65 (C64 version)
3 ;
4
5         .export         _exit
6         .export         __STARTUP__ : absolute = 1      ; Mark as startup
7         .import         initlib, donelib, callirq
8         .import         zerobss
9         .import         callmain
10         .import         RESTOR, BSOUT, CLRCH
11         .import         __INTERRUPTOR_COUNT__
12         .import         __RAM_START__, __RAM_SIZE__     ; Linker generated
13         .import         __STACKSIZE__                   ; Linker generated
14
15         .include        "zeropage.inc"
16         .include        "c64.inc"
17
18
19 ; ------------------------------------------------------------------------
20 ; Startup code
21
22 .segment        "STARTUP"
23
24 Start:
25
26 ; Save the zero page locations we need
27
28         ldx     #zpspace-1
29 L1:     lda     sp,x
30         sta     zpsave,x
31         dex
32         bpl     L1
33
34 ; Switch to second charset
35
36         lda     #14
37         jsr     BSOUT
38
39 ; Switch off the BASIC ROM
40
41         lda     $01
42         pha                     ; Remember the value
43         and     #$F8
44         ora     #$06            ; Enable kernal+I/O, disable basic
45         sta     $01
46
47 ; Clear the BSS data
48
49         jsr     zerobss
50
51 ; Save system settings and setup the stack
52
53         pla
54         sta     mmusave         ; Save the memory configuration
55
56         tsx
57         stx     spsave          ; Save the system stack ptr
58
59         lda     #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
60         sta     sp
61         lda     #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
62         sta     sp+1            ; Set argument stack ptr
63
64 ; If we have IRQ functions, chain our stub into the IRQ vector
65
66         lda     #<__INTERRUPTOR_COUNT__
67         beq     NoIRQ1
68         lda     IRQVec
69         ldx     IRQVec+1
70         sta     IRQInd+1
71         stx     IRQInd+2
72         lda     #<IRQStub
73         ldx     #>IRQStub
74         sei
75         sta     IRQVec
76         stx     IRQVec+1
77         cli
78
79 ; Call module constructors
80
81 NoIRQ1: jsr     initlib
82
83 ; Push arguments and call main
84
85         jsr     callmain
86
87 ; Back from main (This is also the _exit entry). Run module destructors
88
89 _exit:  jsr     donelib
90
91
92 ; Reset the IRQ vector if we chained it.
93
94         pha                     ; Save the return code on stack
95         lda     #<__INTERRUPTOR_COUNT__
96         beq     NoIRQ2
97         lda     IRQInd+1
98         ldx     IRQInd+2
99         sei
100         sta     IRQVec
101         stx     IRQVec+1
102         cli
103
104 ; Copy back the zero page stuff
105
106 NoIRQ2: ldx     #zpspace-1
107 L2:     lda     zpsave,x
108         sta     sp,x
109         dex
110         bpl     L2
111
112 ; Place the program return code into ST
113
114         pla
115         sta     ST
116
117 ; Restore system stuff
118
119         ldx     spsave
120         txs                     ; Restore stack pointer
121         ldx     mmusave
122         stx     $01             ; Restore memory configuration
123
124 ; Reset changed vectors, back to basic
125
126         jmp     RESTOR
127
128 ; ------------------------------------------------------------------------
129 ; The IRQ vector jumps here, if condes routines are defined with type 2.
130
131 IRQStub:
132         cld                             ; Just to be sure
133         jsr     callirq                 ; Call the functions
134         jmp     IRQInd                  ; Jump to the saved IRQ vector
135
136 ; ------------------------------------------------------------------------
137 ; Data
138
139 .data
140
141 IRQInd: jmp     $0000
142
143 .segment        "ZPSAVE"
144
145 zpsave: .res    zpspace
146
147 .bss
148
149 spsave: .res    1
150 mmusave:.res    1