]> git.sur5r.net Git - cc65/blob - libsrc/cbm610/crt0.s
added sleep() implementation
[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, callmain
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 ; Execute the program code
218
219         jmp     Start
220
221 ; ------------------------------------------------------------------------
222 ; Additional data that we need for initialization and that's overwritten
223 ; later
224
225 vectable:
226         jmp     $0000           ; CINT
227         jmp     $0000           ; IOINIT
228         jmp     $0000           ; RAMTAS
229         jmp     $0000           ; RESTOR
230         jmp     $0000           ; VECTOR
231         jmp     $0000           ; SETMSG
232         jmp     $0000           ; SECOND
233         jmp     $0000           ; TKSA
234         jmp     $0000           ; MEMTOP
235         jmp     $0000           ; MEMBOT
236         jmp     SCNKEY
237         jmp     $0000           ; SETTMO
238         jmp     $0000           ; ACPTR
239         jmp     $0000           ; CIOUT
240         jmp     $0000           ; UNTLK
241         jmp     $0000           ; UNLSN
242         jmp     $0000           ; LISTEN
243         jmp     $0000           ; TALK
244         jmp     $0000           ; READST
245         jmp     SETLFS
246         jmp     SETNAM
247         jmp     $0000           ; OPEN
248         jmp     $0000           ; CLOSE
249         jmp     $0000           ; CHKIN
250         jmp     $0000           ; CKOUT
251         jmp     $0000           ; CLRCH
252         jmp     $0000           ; BASIN
253         jmp     $0000           ; BSOUT
254         jmp     $0000           ; LOAD
255         jmp     $0000           ; SAVE
256         jmp     SETTIM
257         jmp     RDTIM
258         jmp     $0000           ; STOP
259         jmp     $0000           ; GETIN
260         jmp     $0000           ; CLALL
261         jmp     UDTIM
262         jmp     SCREEN
263         jmp     PLOT
264         jmp     IOBASE
265         sta     ExecReg
266         rts
267         .byte   $01             ; Filler
268         .word   nmi
269         .word   0               ; Reset - not used
270         .word   irq
271 vectable_size   = * - vectable
272
273 p3vectable:
274         .word   k_irq           ; IRQ user vector
275         .word   k_brk           ; BRK user vector
276         .word   k_nmi           ; NMI user vector
277 p3vectable_size = * - p3vectable
278
279
280 ; ------------------------------------------------------------------------
281 ; This is the program code after setup. It starts at $400
282
283         .res    $400-*
284
285 Start:
286
287 ; Enable interrupts
288
289         cli
290
291 ; Push arguments and call main()
292
293         jsr     callmain
294
295 ; Call module destructors. This is also the _exit entry.
296
297 _exit:  jsr     donelib         ; Run module destructors
298
299 ; Clear the start of the zero page, since it will be interpreted as a
300 ; (garbage) BASIC program otherwise. This is also the default entry for
301 ; the break vector.
302
303 k_brk:  sei
304         lda     #$00
305         ldx     #$3E
306 Clear:  sta     $02,x
307         dex
308         bne     Clear
309
310 ; Setup the welcome code at the stack bottom in the system bank. Use
311 ; the F4/F5 vector to access the system bank
312
313         lda     #$0F
314         sta     IndReg
315         ldy     #$00
316         sty     $F4
317         iny
318         sty     $F5
319         ldy     #reset_size-1
320 @L1:    lda     reset,y
321         sta     ($F4),y
322         dey
323         bne     @L1
324         jmp     Back
325
326 ; ------------------------------------------------------------------------
327 ; Code that is copied into the system bank at $100 when switching back
328
329 reset:  cli
330         jmp     $8000                   ; BASIC cold start
331 reset_size = * - reset
332
333 ; ------------------------------------------------------------------------
334 ; Code for a few simpler kernal calls goes here
335
336 .export IOBASE
337 .proc   IOBASE
338         ldx     cia
339         ldy     cia+1
340         rts
341 .endproc
342
343 .export SCREEN
344 .proc   SCREEN
345         ldx     #80             ; Columns
346         ldy     #25             ; Lines
347         rts
348 .endproc
349
350 .export SETLFS
351 .proc   SETLFS
352         sta     LogicalAdr
353         stx     FirstAdr
354         sty     SecondAdr
355         rts
356 .endproc
357
358 .export SETNAM
359 .proc   SETNAM
360         sta     FileNameLen
361         lda     $00,x
362         sta     FileNameAdrLo
363         lda     $01,x
364         sta     FileNameAdrHi
365         lda     $02,x
366         sta     FileNameAdrSeg
367         rts
368 .endproc
369
370 .export RDTIM
371 .proc   RDTIM
372         sei
373         lda     time+0
374         ldx     time+1
375         ldy     time+2
376         cli
377         rts
378 .endproc
379
380 .export SETTIM
381 .proc   SETTIM
382         sei
383         sta     time+0
384         stx     time+1
385         sty     time+2
386         cli
387         rts
388 .endproc
389
390 ; -------------------------------------------------------------------------
391 ; Data area - switch back to relocatable mode
392
393         .reloc
394
395 .data
396 spsave: .res    1
397
398
399