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