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