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