]> git.sur5r.net Git - cc65/blob - libsrc/cbm610/crt0.s
Use external symbols for the CBM kernal jump table functions. This allows
[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, PLOT, UDTIM, 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     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     SETLFS
251         jmp     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     SETTIM
262         jmp     RDTIM
263         jmp     $0000           ; STOP
264         jmp     $0000           ; GETIN
265         jmp     $0000           ; CLALL
266         jmp     UDTIM
267         jmp     SCREEN
268         jmp     PLOT
269         jmp     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 .export IOBASE
343 .proc   IOBASE
344         ldx     cia
345         ldy     cia+1
346         rts
347 .endproc
348
349 .export SCREEN
350 .proc   SCREEN
351         ldx     #80             ; Columns
352         ldy     #25             ; Lines
353         rts
354 .endproc
355
356 .export SETLFS
357 .proc   SETLFS
358         sta     LogicalAdr
359         stx     FirstAdr
360         sty     SecondAdr
361         rts
362 .endproc
363
364 .export SETNAM
365 .proc   SETNAM
366         sta     FileNameLen
367         lda     $00,x
368         sta     FileNameAdrLo
369         lda     $01,x
370         sta     FileNameAdrHi
371         lda     $02,x
372         sta     FileNameAdrSeg
373         rts
374 .endproc
375
376 .export RDTIM
377 .proc   RDTIM
378         sei
379         lda     time+0
380         ldx     time+1
381         ldy     time+2
382         cli
383         rts
384 .endproc
385
386 .export SETTIM
387 .proc   SETTIM
388         sei
389         sta     time+0
390         stx     time+1
391         sty     time+2
392         cli
393         rts
394 .endproc
395
396 ; -------------------------------------------------------------------------
397 ; Data area - switch back to relocatable mode
398
399         .reloc
400
401 .data
402 spsave: .res    1
403
404
405