]> git.sur5r.net Git - cc65/blob - libsrc/plus4/crt0.s
Added VIC2 sprites as output format. Started to code the processing pipeline:
[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 and return to BASIC
116
117         sta     ENABLE_ROM
118         rts
119
120 ; ------------------------------------------------------------------------
121 ; IRQ handler. The handler in the ROM enables the kernal and jumps to
122 ; $CE00, where the ROM code checks for a BRK or IRQ and branches via the
123 ; indirect vectors at $314/$316.
124 ; To make our stub as fast as possible, we skip the whole part of the ROM
125 ; handler and jump to the indirect vectors directly. We do also call our
126 ; own interrupt handlers if we have any, so they need not use $314.
127
128 .segment        "LOWCODE"
129
130 IRQ:    cld                     ; Just to be sure
131         pha
132         txa
133         pha
134         tya
135         pha
136         tsx                     ; Get the stack pointer
137         lda     $0104,x         ; Get the saved status register
138         and     #$10            ; Test for BRK bit
139         bne     dobreak
140
141 ; It's an IRQ and RAM is enabled. If we have handlers, call them. We will use
142 ; a flag here instead of loading __INTERRUPTOR_COUNT__ directly, since the
143 ; condes function is not reentrant. The irqcount flag will be set/reset from
144 ; the main code, to avoid races.
145
146         ldy     irqcount
147         beq     @L1
148         jsr     callirq_y       ; Call the IRQ functions
149
150 ; Since the ROM handler will end with an RTI, we have to fake an IRQ return
151 ; on stack, so we get control of the CPU after the ROM handler and can switch
152 ; back to RAM.
153
154 @L1:    lda     #>irq_ret       ; Push new return address
155         pha
156         lda     #<irq_ret
157         pha
158         php                     ; Push faked IRQ frame on stack
159         pha                     ; Push faked A register
160         pha                     ; Push faked X register
161         pha                     ; Push faked Y register
162         sta     ENABLE_ROM      ; Switch to ROM
163         jmp     (IRQVec)        ; Jump indirect to kernal irq handler
164
165 irq_ret:
166         sta     ENABLE_RAM      ; Switch back to RAM
167         pla
168         tay
169         pla
170         tax
171         pla
172         rti
173
174 dobreak:
175         lda     brk_jmp+2       ; Check high byte of address
176         beq     nohandler
177         jmp     brk_jmp         ; Jump to the handler
178
179 ; No break handler installed, jump to ROM
180
181 nohandler:
182         sta     ENABLE_ROM
183         jmp     (BRKVec)        ; Jump indirect to the break vector
184
185 ; ------------------------------------------------------------------------
186 ; Data
187
188 .data
189
190 ; BRK handling
191 brk_jmp:        jmp     $0000
192
193 spsave:         .res    1
194
195 irqcount:       .byte   0
196
197 .segment        "ZPSAVE"
198
199 zpsave:         .res    zpspace
200
201