]> git.sur5r.net Git - cc65/blob - libsrc/plus4/crt0.s
Corrected screensize function by Stefan Haubenthal.
[cc65] / libsrc / plus4 / crt0.s
1 ;
2 ; Startup code for cc65 (Plus/4 version)
3 ;
4
5         .export         _exit
6         .export         brk_jmp
7         .export         __STARTUP__ : absolute = 1      ; Mark as startup
8
9         .import         callirq_y, initlib, donelib
10         .import         callmain, zerobss
11         .import         __INTERRUPTOR_COUNT__
12         .import         __RAM_START__, __RAM_SIZE__     ; Linker generated
13         .import         __STACKSIZE__                   ; Linker generated
14
15         .include        "zeropage.inc"
16         .include        "plus4.inc"
17
18
19 ; ------------------------------------------------------------------------
20 ; Constants
21
22 IRQInd          = $500  ; JMP $0000 - used as indirect IRQ vector
23
24 ; ------------------------------------------------------------------------
25 ; Startup code
26
27 .segment        "STARTUP"
28
29 Start:
30
31 ; Save the zero page locations we need
32
33         sei                     ; No interrupts since we're banking out the ROM
34         sta     ENABLE_RAM
35         ldx     #zpspace-1
36 L1:     lda     sp,x
37         sta     zpsave,x
38         dex
39         bpl     L1
40         sta     ENABLE_ROM
41         cli
42
43 ; Switch to second charset
44
45         lda     #14
46         jsr     $FFD2           ; BSOUT
47
48 ; Save system stuff and setup the stack. The stack starts at the top of the
49 ; usable RAM.
50
51         tsx
52         stx     spsave          ; save system stk ptr
53
54         lda     #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
55         sta     sp
56         lda     #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
57         sta     sp+1
58
59 ; Setup the IRQ vector in the banked RAM and switch off the ROM
60
61         ldx     #<IRQ
62         ldy     #>IRQ
63         sei                     ; No ints, handler not yet in place
64         sta     ENABLE_RAM
65         stx     $FFFE           ; Install interrupt handler
66         sty     $FFFF
67         cli                     ; Allow interrupts
68
69 ; Clear the BSS data
70
71         jsr     zerobss
72
73 ; Initialize irqcount, which means that from now own custom linked in IRQ
74 ; handlers (via condes) will be called.
75
76         lda     #.lobyte(__INTERRUPTOR_COUNT__*2)
77         sta     irqcount
78
79 ; Call module constructors
80
81         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:  pha                     ; Save the return code
90         jsr     donelib         ; Run module destructors
91
92 ; Disable chained IRQ handlers
93
94         lda     #0
95         sta     irqcount        ; Disable custom IRQ handlers
96
97 ; Copy back the zero page stuff
98
99         ldx     #zpspace-1
100 L2:     lda     zpsave,x
101         sta     sp,x
102         dex
103         bpl     L2
104
105 ; Place the program return code into ST
106
107         pla
108         sta     ST
109
110 ; Restore the stack pointer
111
112         ldx     spsave
113         txs
114
115 ; Enable the ROM, reset changed vectors and return to BASIC
116
117         sta     ENABLE_ROM
118         jmp     $FF8A           ; RESTOR
119
120
121 ; ------------------------------------------------------------------------
122 ; IRQ handler. The handler in the ROM enables the kernal and jumps to
123 ; $CE00, where the ROM code checks for a BRK or IRQ and branches via the
124 ; indirect vectors at $314/$316.
125 ; To make our stub as fast as possible, we skip the whole part of the ROM
126 ; handler and jump to the indirect vectors directly. We do also call our
127 ; own interrupt handlers if we have any, so they need not use $314.
128
129 .segment        "LOWCODE"
130
131 IRQ:    cld                     ; Just to be sure
132         pha
133         txa
134         pha
135         tya
136         pha
137         tsx                     ; Get the stack pointer
138         lda     $0104,x         ; Get the saved status register
139         and     #$10            ; Test for BRK bit
140         bne     dobreak
141
142 ; It's an IRQ and RAM is enabled. If we have handlers, call them. We will use
143 ; a flag here instead of loading __INTERRUPTOR_COUNT__ directly, since the
144 ; condes function is not reentrant. The irqcount flag will be set/reset from
145 ; the main code, to avoid races.
146
147         ldy     irqcount
148         beq     @L1
149         jsr     callirq_y       ; Call the IRQ functions
150
151 ; Since the ROM handler will end with an RTI, we have to fake an IRQ return
152 ; on stack, so we get control of the CPU after the ROM handler and can switch
153 ; back to RAM.
154
155 @L1:    lda     #>irq_ret       ; Push new return address
156         pha
157         lda     #<irq_ret
158         pha
159         php                     ; Push faked IRQ frame on stack
160         pha                     ; Push faked A register
161         pha                     ; Push faked X register
162         pha                     ; Push faked Y register
163         sta     ENABLE_ROM      ; Switch to ROM
164         jmp     (IRQVec)        ; Jump indirect to kernal irq handler
165
166 irq_ret:
167         sta     ENABLE_RAM      ; Switch back to RAM
168         pla
169         tay
170         pla
171         tax
172         pla
173         rti
174
175 dobreak:
176         lda     brk_jmp+2       ; Check high byte of address
177         beq     nohandler
178         jmp     brk_jmp         ; Jump to the handler
179
180 ; No break handler installed, jump to ROM
181
182 nohandler:
183         sta     ENABLE_ROM
184         jmp     (BRKVec)        ; Jump indirect to the break vector
185
186 ; ------------------------------------------------------------------------
187 ; Data
188
189 .data
190
191 ; BRK handling
192 brk_jmp:        jmp     $0000
193
194 spsave:         .res    1
195
196 irqcount:       .byte   0
197
198 .segment        "ZPSAVE"
199
200 zpsave:         .res    zpspace
201
202