]> git.sur5r.net Git - cc65/blob - libsrc/cbm610/crt0.s
c13bcb0436c40e2e9a22327731440b96420c16f2
[cc65] / libsrc / cbm610 / crt0.s
1 ;
2 ; Startup code for cc65 (CBM 600/700 version)
3 ;
4 ; This must be the *first* file on the linker command line
5 ;
6
7         .export         _exit
8         .exportzp       crtc, sid, IPCcia, cia, acia, tpi1, tpi2, ktab1
9         .exportzp       ktab2, ktab3, ktab4, time, RecvBuf, SendBuf
10
11         .import         initlib, donelib
12         .import         push0, _main
13         .import         __BSS_RUN__, __BSS_SIZE__
14         .import         irq, nmi
15         .import         k_irq, k_nmi, k_plot, k_udtim, k_scnkey
16
17         .include        "zeropage.inc"
18         .include        "cbm610.inc"
19
20
21 ; ------------------------------------------------------------------------
22 ; BASIC header and a small BASIC program. Since it is not possible to start
23 ; programs in other banks using SYS, the BASIC program will write a small
24 ; machine code program into memory at $100 and start that machine code
25 ; program. The machine code program will then start the machine language
26 ; code in bank 1, which will initialize the system by copying stuff from
27 ; the system bank, and start the application.
28 ;
29 ; Here's the basic program that's in the following lines:
30 ;
31 ; 10 for i=0 to 4
32 ; 20 read j
33 ; 30 poke 256+i,j
34 ; 40 next i
35 ; 50 sys 256
36 ; 60 data 120,169,1,133,0
37 ;
38 ; The machine program in the data lines is:
39 ;
40 ; sei
41 ; lda     #$01
42 ; sta     $00           <-- Switch to bank 1 after this command
43 ;
44 ; Initialization is not only complex because of the jumping from one bank
45 ; into another. but also because we want to save memory, and because of
46 ; this, we will use the system memory ($00-$3FF) for initialization stuff
47 ; that is overwritten later.
48 ;
49
50 .code
51
52 ; To make things more simple, make the code of this module absolute.
53
54         .org    $0001
55 Head:   .byte   $03,$00,$11,$00,$0a,$00,$81,$20,$49,$b2,$30,$20,$a4,$20,$34,$00
56         .byte   $19,$00,$14,$00,$87,$20,$4a,$00,$27,$00,$1e,$00,$97,$20,$32,$35
57         .byte   $36,$aa,$49,$2c,$4a,$00,$2f,$00,$28,$00,$82,$20,$49,$00,$39,$00
58         .byte   $32,$00,$9e,$20,$32,$35,$36,$00,$4f,$00,$3c,$00,$83,$20,$31,$32
59         .byte   $30,$2c,$31,$36,$39,$2c,$31,$2c,$31,$33,$33,$2c,$30,$00,$00,$00
60
61 ; Since we need some vectors to access stuff in the system bank for our own,
62 ; we will include them here, starting from $60:
63
64         .res    $60-*
65
66 crtc:           .word   $d800
67 sid:            .word   $da00
68 IPCcia:         .word   $db00
69 cia:            .word   $dc00
70 acia:           .word   $dd00
71 tpi1:           .word   $de00
72 tpi2:           .word   $df00
73 ktab1:          .word   $ea29
74 ktab2:          .word   $ea89
75 ktab3:          .word   $eae9
76 ktab4:          .word   $eb49
77 time:           .dword  $0000
78 RecvBuf:        .word   $0100           ; RS232 received buffer
79 SendBuf:        .word   $0200           ; RS232 send buffer
80
81
82 ; The code in the target bank when switching back will be put at the bottom
83 ; of the stack. We will jump here to switch segments. The range $F2..$FF is
84 ; not used by any kernal routine.
85
86         .res    $F8-*
87 Back:   ldx     spsave
88         txs
89         lda     IndReg
90         sta     ExecReg
91
92 ; The following code is a copy of the code that is poked in the system bank
93 ; memory by the basic header program, it's only for documentation and not
94 ; actually used here:
95
96         sei
97         lda     #$01
98         sta     ExecReg
99
100 ; This is the actual starting point of our code after switching banks for
101 ; startup. Beware: The following code will get overwritten as soon as we
102 ; use the stack (since it's in page 1)!
103
104         tsx
105         stx     spsave          ; Save the system stackpointer
106         ldx     #$FF
107         txs                     ; Set up our own stack
108
109 ; Set the interrupt, NMI and other vectors
110
111         ldy     #vectable_size
112 L0:     lda     vectable-1,y
113         sta     $FF80,y
114         dey
115         bne     L0
116
117 ; Switch the indirect segment to the system bank
118
119         lda     #$0F
120         sta     IndReg
121
122 ; Copy the kernal zero page ($90-$F2) from the system bank
123
124         lda     #$90
125         sta     ptr1
126         lda     #$00
127         sta     ptr1+1
128         ldy     #$62-1
129 L1:     lda     (ptr1),y
130         sta     $90,y
131         dey
132         bpl     L1
133
134 ; Copy the page 3 vectors in place
135
136         ldy     #$00
137 L2:     lda     p3vectable,y
138         sta     $300,y
139         iny
140         cpy     #p3vectable_size
141         bne     L2
142
143 ; Copy the rest of page 3 from the system bank
144
145         lda     #$00
146         sta     ptr1
147         lda     #$03
148         sta     ptr1+1
149 L3:     lda     (ptr1),y
150         sta     $300,y
151         iny
152         bne     L3
153
154 ; Set the indirect segment to bank we're executing in
155
156         lda     ExecReg
157         sta     IndReg
158
159 ; Zero the BSS segment. We will do that here instead calling the routine
160 ; in the common library, since we have the memory anyway, and this way,
161 ; it's reused later.
162
163         lda     #<__BSS_RUN__
164         sta     ptr1
165         lda     #>__BSS_RUN__
166         sta     ptr1+1
167         lda     #0
168         tay
169
170 ; Clear full pages
171
172         ldx     #>__BSS_SIZE__
173         beq     Z2
174 Z1:     sta     (ptr1),y
175         iny
176         bne     Z1
177         inc     ptr1+1                  ; Next page
178         dex
179         bne     Z1
180
181 ; Clear the remaining page
182
183 Z2:     ldx     #<__BSS_SIZE__
184         beq     Z4
185 Z3:     sta     (ptr1),y
186         iny
187         dex
188         bne     Z3
189 Z4:
190
191 ; Setup the C stack
192
193         lda     #<$FF81
194         sta     sp
195         lda     #>$FF81
196         sta     sp+1
197
198 ; We expect to be in page 2 now
199
200 .if     (* < $1FD)
201         jmp     $200
202         .res    $200-*
203 .endif
204 .if     (* < $200)
205         .res    $200-*,$EA
206 .endif
207 .if     (* >= $2F0)
208 .error  "Code range invalid"
209 .endif
210
211 ; This code is in page 2, so we may now start calling subroutines safely,
212 ; since the code we execute is no longer in the stack page.
213 ; Call module constructors
214
215         jsr     initlib
216
217 ; Create the (empty) command line for the program
218
219         jsr     push0           ; argc
220         jsr     push0           ; argv
221
222 ; Execute the program code
223
224         jmp     Start
225
226 ; ------------------------------------------------------------------------
227 ; Additional data that we need for initialization and that's overwritten
228 ; later
229
230 vectable:
231         jmp     $0000           ; CINT
232         jmp     $0000           ; IOINIT
233         jmp     $0000           ; RAMTAS
234         jmp     $0000           ; RESTOR
235         jmp     $0000           ; VECTOR
236         jmp     $0000           ; SETMSG
237         jmp     $0000           ; SECOND
238         jmp     $0000           ; TKSA
239         jmp     $0000           ; MEMTOP
240         jmp     $0000           ; MEMBOT
241         jmp     k_scnkey        ; SCNKEY
242         jmp     $0000           ; SETTMO
243         jmp     $0000           ; ACPTR
244         jmp     $0000           ; CIOUT
245         jmp     $0000           ; UNTLK
246         jmp     $0000           ; UNLSN
247         jmp     $0000           ; LISTEN
248         jmp     $0000           ; TALK
249         jmp     $0000           ; READST
250         jmp     k_setlfs        ; SETLFS
251         jmp     k_setnam        ; SETNAM
252         jmp     $0000           ; OPEN
253         jmp     $0000           ; CLOSE
254         jmp     $0000           ; CHKIN
255         jmp     $0000           ; CKOUT
256         jmp     $0000           ; CLRCH
257         jmp     $0000           ; BASIN
258         jmp     $0000           ; BSOUT
259         jmp     $0000           ; LOAD
260         jmp     $0000           ; SAVE
261         jmp     k_settim        ; SETTIM
262         jmp     k_rdtim         ; RDTIM
263         jmp     $0000           ; STOP
264         jmp     $0000           ; GETIN
265         jmp     $0000           ; CLALL
266         jmp     k_udtim         ; UDTIM
267         jmp     k_screen        ; SCREEN
268         jmp     k_plot          ; PLOT
269         jmp     k_iobase        ; IOBASE
270         sta     ExecReg
271         rts
272         .byte   $01             ; Filler
273         .word   nmi
274         .word   0               ; Reset - not used
275         .word   irq
276 vectable_size   = * - vectable
277
278 p3vectable:
279         .word   k_irq           ; IRQ user vector
280         .word   k_brk           ; BRK user vector
281         .word   k_nmi           ; NMI user vector
282 p3vectable_size = * - p3vectable
283
284
285 ; ------------------------------------------------------------------------
286 ; This is the program code after setup. It starts at $400
287
288         .res    $400-*
289
290 Start:
291
292 ; Enable interrupts
293
294         cli
295
296 ; Call the user code
297
298         ldy     #4              ; Argument size
299         jsr     _main           ; call the users code
300
301 ; Call module destructors. This is also the _exit entry.
302
303 _exit:  jsr     donelib         ; Run module destructors
304
305 ; Clear the start of the zero page, since it will be interpreted as a
306 ; (garbage) BASIC program otherwise. This is also the default entry for
307 ; the break vector.
308
309 k_brk:  sei
310         lda     #$00
311         ldx     #$3E
312 Clear:  sta     $02,x
313         dex
314         bne     Clear
315
316 ; Setup the welcome code at the stack bottom in the system bank. Use
317 ; the F4/F5 vector to access the system bank
318
319         lda     #$0F
320         sta     IndReg
321         ldy     #$00
322         sty     $F4
323         iny
324         sty     $F5
325         ldy     #reset_size-1
326 @L1:    lda     reset,y
327         sta     ($F4),y
328         dey
329         bne     @L1
330         jmp     Back
331
332 ; ------------------------------------------------------------------------
333 ; Code that is copied into the system bank at $100 when switching back
334
335 reset:  cli
336         jmp     $8000                   ; BASIC cold start
337 reset_size = * - reset
338
339 ; ------------------------------------------------------------------------
340 ; Code for a few simpler kernal calls goes here
341
342 k_iobase:
343         ldx     cia
344         ldy     cia+1
345         rts
346
347 k_screen:
348         ldx     #80             ; Columns
349         ldy     #25             ; Lines
350         rts
351
352 k_setlfs:
353         sta     LogicalAdr
354         stx     FirstAdr
355         sty     SecondAdr
356         rts
357
358 k_setnam:
359         sta     FileNameLen
360         lda     $00,x
361         sta     FileNameAdrLo
362         lda     $01,x
363         sta     FileNameAdrHi
364         lda     $02,x
365         sta     FileNameAdrSeg
366         rts
367
368 k_rdtim:
369         sei
370         lda     time+0
371         ldx     time+1
372         ldy     time+2
373         cli
374         rts
375
376 k_settim:
377         sei
378         sta     time+0
379         stx     time+1
380         sty     time+2
381         cli
382         rts
383
384 ; -------------------------------------------------------------------------
385 ; Data area - switch back to relocatable mode
386
387         .reloc
388
389 .data
390 spsave: .res    1
391
392
393