]> git.sur5r.net Git - cc65/blob - libsrc/cbm510/crt0.s
Fixed capslock on startup
[cc65] / libsrc / cbm510 / crt0.s
1 ;
2 ; Startup code for cc65 (CBM 500 version)
3 ;
4 ; This must be the *first* file on the linker command line
5 ;
6
7         .export         _exit
8
9         .import         _clrscr, initlib, donelib
10         .import         push0, callmain
11         .import         __CHARRAM_START__, __CHARRAM_SIZE__, __VIDRAM_START__
12         .import         __EXTZP_RUN__, __EXTZP_SIZE__
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        "extzp.inc"
19         .include        "cbm510.inc"
20
21
22 ; ------------------------------------------------------------------------
23 ; BASIC header and a small BASIC program. Since it is not possible to start
24 ; programs in other banks using SYS, the BASIC program will write a small
25 ; machine code program into memory at $100 and start that machine code
26 ; program. The machine code program will then start the machine language
27 ; code in bank 0, which will initialize the system by copying stuff from
28 ; the system bank, and start the application.
29 ;
30 ; Here's the basic program that's in the following lines:
31 ;
32 ; 10 for i=0 to 4
33 ; 20 read j
34 ; 30 poke 256+i,j
35 ; 40 next i
36 ; 50 sys 256
37 ; 60 data 120,169,0,133,0
38 ;
39 ; The machine program in the data lines is:
40 ;
41 ; sei
42 ; lda     #$00
43 ; sta     $00           <-- Switch to bank 0 after this command
44 ;
45 ; Initialization is not only complex because of the jumping from one bank
46 ; into another. but also because we want to save memory, and because of
47 ; this, we will use the system memory ($00-$3FF) for initialization stuff
48 ; that is overwritten later.
49 ;
50
51 .code
52
53 ; To make things more simple, make the code of this module absolute.
54
55         .org    $0001
56 Head:   .byte   $03,$00,$11,$00,$0a,$00,$81,$20,$49,$b2,$30,$20,$a4,$20,$34,$00
57         .byte   $19,$00,$14,$00,$87,$20,$4a,$00,$27,$00,$1e,$00,$97,$20,$32,$35
58         .byte   $36,$aa,$49,$2c,$4a,$00,$2f,$00,$28,$00,$82,$20,$49,$00,$39,$00
59         .byte   $32,$00,$9e,$20,$32,$35,$36,$00,$4f,$00,$3c,$00,$83,$20,$31,$32
60         .byte   $30,$2c,$31,$36,$39,$2c,$30,$2c,$31,$33,$33,$2c,$30,$00,$00,$00
61
62 ; The code in the target bank when switching back will be put at the bottom
63 ; of the stack. We will jump here to switch segments. The range $F2..$FF is
64 ; not used by any kernal routine.
65
66         .res    $F8-*
67 Back:   ldx     spsave
68         txs
69         lda     IndReg
70         sta     ExecReg
71
72 ; The following code is a copy of the code that is poked in the system bank
73 ; memory by the basic header program, it's only for documentation and not
74 ; actually used here:
75
76         sei
77         lda     #$00
78         sta     ExecReg
79
80 ; This is the actual starting point of our code after switching banks for
81 ; startup. Beware: The following code will get overwritten as soon as we
82 ; use the stack (since it's in page 1)!
83
84         tsx
85         stx     spsave          ; Save the system stackpointer
86         ldx     #$FF
87         txs                     ; Set up our own stack
88
89 ; Set the interrupt, NMI and other vectors
90
91         ldy     #vectable_size
92 L0:     lda     vectable-1,y
93         sta     $FF81-1,y
94         dey
95         bne     L0
96
97 ; Initialize the extended zero page variables
98
99         ldx     #zptable_size
100 L1:     lda     zptable-1,x
101         sta     <(__EXTZP_RUN__-1),x
102         dex
103         bne     L1
104
105 ; Switch the indirect segment to the system bank
106
107         lda     #$0F
108         sta     IndReg
109
110 ; Copy the kernal zero page ($90-$F2) from the system bank
111
112         lda     #$90
113         sta     ptr1
114         lda     #$00
115         sta     ptr1+1
116         ldy     #$62-1
117 L2:     lda     (ptr1),y
118         sta     $90,y
119         dey
120         bpl     L2
121
122 ; Copy the page 3 vectors in place
123
124         ldy     #$00
125 L3:     lda     p3vectable,y
126         sta     $300,y
127         iny
128         cpy     #p3vectable_size
129         bne     L3
130
131 ; Copy the rest of page 3 from the system bank
132
133         lda     #$00
134         sta     ptr1
135         lda     #$03
136         sta     ptr1+1
137 L4:     lda     (ptr1),y
138         sta     $300,y
139         iny
140         bne     L4
141
142 ; Set the indirect segment to bank we're executing in
143
144         lda     ExecReg
145         sta     IndReg
146
147 ; Zero the BSS segment. We will do that here instead calling the routine
148 ; in the common library, since we have the memory anyway, and this way,
149 ; it's reused later.
150
151         lda     #<__BSS_RUN__
152         sta     ptr1
153         lda     #>__BSS_RUN__
154         sta     ptr1+1
155         lda     #0
156         tay
157
158 ; Clear full pages
159
160         ldx     #>__BSS_SIZE__
161         beq     Z2
162 Z1:     sta     (ptr1),y
163         iny
164         bne     Z1
165         inc     ptr1+1                  ; Next page
166         dex
167         bne     Z1
168
169 ; Clear the remaining page
170
171 Z2:     ldx     #<__BSS_SIZE__
172         beq     Z4
173 Z3:     sta     (ptr1),y
174         iny
175         dex
176         bne     Z3
177 Z4:
178
179 ; Setup the C stack
180
181         lda     #<$FF81
182         sta     sp
183         lda     #>$FF81
184         sta     sp+1
185
186 ; We expect to be in page 2 now
187
188 .if     (* < $1FD)
189         jmp     $200
190         .res    $200-*
191 .endif
192 .if     (* < $200)
193         .res    $200-*,$EA
194 .endif
195 .if     (* >= $2F0)
196 .error  "Code range invalid"
197 .endif
198
199 ; This code is in page 2, so we may now start calling subroutines safely,
200 ; since the code we execute is no longer in the stack page.
201
202 ; Copy the character rom from the system bank into the execution bank
203
204         lda     #<$C000
205         sta     ptr1
206         lda     #>$C000
207         sta     ptr1+1
208         lda     #<__CHARRAM_START__
209         sta     ptr2
210         lda     #>__CHARRAM_START__
211         sta     ptr2+1
212         lda     #>__CHARRAM_SIZE__      ; 16 * 256 bytes to copy
213         sta     tmp1
214         ldy     #$00
215 ccopy:  lda     #$0F
216         sta     IndReg                  ; Access the system bank
217 ccopy1: lda     (ptr1),y
218         sta     __VIDRAM_START__,y
219         iny
220         bne     ccopy1
221         lda     ExecReg
222         sta     IndReg
223 ccopy2: lda     __VIDRAM_START__,y
224         sta     (ptr2),y
225         iny
226         bne     ccopy2
227         inc     ptr1+1
228         inc     ptr2+1                  ; Bump high pointer bytes
229         dec     tmp1
230         bne     ccopy
231
232 ; Clear the video memory. We will do this before switching the video to bank 0
233 ; to avoid garbage when doing so.
234
235         jsr     _clrscr
236
237 ; Reprogram the VIC so that the text screen and the character ROM is in the
238 ; execution bank. This is done in three steps:
239
240         lda     #$0F                    ; We need access to the system bank
241         sta     IndReg
242
243 ; Place the VIC video RAM into bank 0
244 ; CA (STATVID)   = 0
245 ; CB (VICDOTSEL) = 0
246
247         ldy     #tpiCtrlReg
248         lda     (tpi1),y
249         sta     vidsave+0
250         and     #%00001111
251         ora     #%10100000
252         sta     (tpi1),y
253
254 ; Set bit 14/15 of the VIC address range to the high bits of __VIDRAM_START__
255 ; PC6/PC7 (VICBANKSEL 0/1) = 11
256
257         ldy     #tpiPortC
258         lda     (tpi2),y
259         sta     vidsave+1
260         and     #$3F
261         ora     #<((>__VIDRAM_START__) & $C0)
262         sta     (tpi2),y
263
264 ; Set the VIC base address register to the addresses of the video and
265 ; character RAM.
266
267         ldy     #VIC_VIDEO_ADR
268         lda     (vic),y
269         sta     vidsave+2
270         and     #$01
271         ora     #<(((__VIDRAM_START__ >> 6) & $F0) | ((__CHARRAM_START__ >> 10) & $0E) | $02)
272 ;       and     #$0F
273 ;       ora     #<(((>__VIDRAM_START__) << 2) & $F0)
274         sta     (vic),y
275
276 ; Switch back to the execution bank
277
278         lda     ExecReg
279         sta     IndReg
280
281 ; Call module constructors
282
283         jsr     initlib
284
285 ; Execute the program code
286
287         jmp     Start
288
289 ; ------------------------------------------------------------------------
290 ; Additional data that we need for initialization and that's overwritten
291 ; later
292
293 zptable:
294         .word   $d800           ; vic
295         .word   $da00           ; sid
296         .word   $db00           ; cia1
297         .word   $dc00           ; cia2
298         .word   $dd00           ; acia
299         .word   $de00           ; tpi1
300         .word   $df00           ; tpi2
301         .word   $eab1           ; ktab1
302         .word   $eb11           ; ktab2
303         .word   $eb71           ; ktab3
304         .word   $ebd1           ; ktab4
305         .dword  $0000           ; time
306         .word   $0100           ; RecvBuf
307         .word   $0200           ; SendBuf
308 zptable_size    = * - zptable
309
310 vectable:
311         jmp     $0000           ; CINT
312         jmp     $0000           ; IOINIT
313         jmp     $0000           ; RAMTAS
314         jmp     $0000           ; RESTOR
315         jmp     $0000           ; VECTOR
316         jmp     $0000           ; SETMSG
317         jmp     $0000           ; SECOND
318         jmp     $0000           ; TKSA
319         jmp     $0000           ; MEMTOP
320         jmp     $0000           ; MEMBOT
321         jmp     SCNKEY
322         jmp     $0000           ; SETTMO
323         jmp     $0000           ; ACPTR
324         jmp     $0000           ; CIOUT
325         jmp     $0000           ; UNTLK
326         jmp     $0000           ; UNLSN
327         jmp     $0000           ; LISTEN
328         jmp     $0000           ; TALK
329         jmp     $0000           ; READST
330         jmp     SETLFS
331         jmp     SETNAM
332         jmp     $0000           ; OPEN
333         jmp     $0000           ; CLOSE
334         jmp     $0000           ; CHKIN
335         jmp     $0000           ; CKOUT
336         jmp     $0000           ; CLRCH
337         jmp     $0000           ; BASIN
338         jmp     $0000           ; BSOUT
339         jmp     $0000           ; LOAD
340         jmp     $0000           ; SAVE
341         jmp     SETTIM
342         jmp     RDTIM
343         jmp     $0000           ; STOP
344         jmp     $0000           ; GETIN
345         jmp     $0000           ; CLALL
346         jmp     UDTIM
347         jmp     SCREEN
348         jmp     PLOT
349         jmp     IOBASE
350         sta     ExecReg
351         rts
352         .byte   $01             ; Filler
353         .word   nmi
354         .word   0               ; Reset - not used
355         .word   irq
356 vectable_size   = * - vectable
357
358 p3vectable:
359         .word   k_irq           ; IRQ user vector
360         .word   k_brk           ; BRK user vector
361         .word   k_nmi           ; NMI user vector
362 p3vectable_size = * - p3vectable
363
364
365 ; ------------------------------------------------------------------------
366 ; This is the program code after setup. It starts at $400
367
368         .res    $400-*
369
370 Start:
371
372 ; Enable interrupts
373
374         cli
375
376 ; Push arguments and call main()
377
378         jsr     callmain
379
380 ; Call module destructors. This is also the _exit entry.
381
382 _exit:  jsr     donelib         ; Run module destructors
383
384 ; We need access to the system bank now
385
386         lda     #$0F
387         sta     IndReg
388
389 ; Switch back the video to the system bank
390
391         ldy     #tpiCtrlReg
392         lda     vidsave+0
393         sta     (tpi1),y
394
395         ldy     #tpiPortC
396         lda     vidsave+1
397         sta     (tpi2),y
398
399         ldy     #VIC_VIDEO_ADR
400         lda     vidsave+2
401         sta     (vic),y
402
403 ; Clear the start of the zero page, since it will be interpreted as a
404 ; (garbage) BASIC program otherwise. This is also the default entry for
405 ; the break vector.
406
407 k_brk:  sei
408         lda     #$00
409         ldx     #$3E
410 Clear:  sta     $02,x
411         dex
412         bne     Clear
413
414 ; Setup the welcome code at the stack bottom in the system bank. Use
415 ; the F4/F5 vector to access the system bank
416
417         ldy     #$00
418         sty     $F4
419         iny
420         sty     $F5
421         ldy     #reset_size-1
422 @L1:    lda     reset,y
423         sta     ($F4),y
424         dey
425         bne     @L1
426         jmp     Back
427
428 ; ------------------------------------------------------------------------
429 ; Code that is copied into the system bank at $100 when switching back
430
431 reset:  cli
432         jmp     $8000                   ; BASIC cold start
433 reset_size = * - reset
434
435 ; ------------------------------------------------------------------------
436 ; Code for a few simpler kernal calls goes here
437
438 .export IOBASE
439 .proc   IOBASE
440         ldx     cia2
441         ldy     cia2+1
442         rts
443 .endproc
444
445 .export SCREEN
446 .proc   SCREEN
447         ldx     #40             ; Columns
448         ldy     #25             ; Lines
449         rts
450 .endproc
451
452 .export SETLFS
453 .proc   SETLFS
454         sta     LogicalAdr
455         stx     FirstAdr
456         sty     SecondAdr
457         rts
458 .endproc
459
460 .export SETNAM
461 .proc   SETNAM
462         sta     FileNameLen
463         lda     $00,x
464         sta     FileNameAdrLo
465         lda     $01,x
466         sta     FileNameAdrHi
467         lda     $02,x
468         sta     FileNameAdrSeg
469         rts
470 .endproc
471
472 .export RDTIM
473 .proc   RDTIM
474         sei
475         lda     time+0
476         ldx     time+1
477         ldy     time+2
478         cli
479         rts
480 .endproc
481
482 .export SETTIM
483 .proc   SETTIM
484         sei
485         sta     time+0
486         stx     time+1
487         sty     time+2
488         cli
489         rts
490 .endproc
491
492 ; -------------------------------------------------------------------------
493 ; Data area - switch back to relocatable mode
494
495         .reloc
496
497 .data
498 spsave: .res    1
499 vidsave:.res    3
500
501