2 ; Startup code for cc65 (CBM 500 version)
4 ; This must be the *first* file on the linker command line
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__
15 .import k_irq, k_nmi, PLOT, UDTIM, SCNKEY
17 .include "zeropage.inc"
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.
30 ; Here's the basic program that's in the following lines:
37 ; 60 data 120,169,0,133,0
39 ; The machine program in the data lines is:
43 ; sta $00 <-- Switch to bank 0 after this command
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.
53 ; To make things more simple, make the code of this module absolute.
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
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.
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
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)!
85 stx spsave ; Save the system stackpointer
87 txs ; Set up our own stack
89 ; Set the interrupt, NMI and other vectors
97 ; Initialize the extended zero page variables
101 sta <(__EXTZP_RUN__-1),x
105 ; Switch the indirect segment to the system bank
110 ; Copy the kernal zero page ($90-$F2) from the system bank
122 ; Copy the page 3 vectors in place
131 ; Copy the rest of page 3 from the system bank
142 ; Set the indirect segment to bank we're executing in
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,
165 inc ptr1+1 ; Next page
169 ; Clear the remaining page
171 Z2: ldx #<__BSS_SIZE__
186 ; We expect to be in page 2 now
196 .error "Code range invalid"
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.
202 ; Copy the character rom from the system bank into the execution bank
208 lda #<__CHARRAM_START__
210 lda #>__CHARRAM_START__
212 lda #>__CHARRAM_SIZE__ ; 16 * 256 bytes to copy
216 sta IndReg ; Access the system bank
218 sta __VIDRAM_START__,y
223 ccopy2: lda __VIDRAM_START__,y
228 inc ptr2+1 ; Bump high pointer bytes
232 ; Clear the video memory. We will do this before switching the video to bank 0
233 ; to avoid garbage when doing so.
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:
240 lda #$0F ; We need access to the system bank
243 ; Place the VIC video RAM into bank 0
254 ; Set bit 14/15 of the VIC address range to the high bits of __VIDRAM_START__
255 ; PC6/PC7 (VICBANKSEL 0/1) = 11
261 ora #<((>__VIDRAM_START__) & $C0)
264 ; Set the VIC base address register to the addresses of the video and
271 ora #<(((__VIDRAM_START__ >> 6) & $F0) | ((__CHARRAM_START__ >> 10) & $0E) | $02)
273 ; ora #<(((>__VIDRAM_START__) << 2) & $F0)
276 ; Switch back to the execution bank
281 ; Call module constructors
285 ; Execute the program code
289 ; ------------------------------------------------------------------------
290 ; Additional data that we need for initialization and that's overwritten
306 .word $0100 ; RecvBuf
307 .word $0200 ; SendBuf
308 zptable_size = * - zptable
354 .word 0 ; Reset - not used
356 vectable_size = * - vectable
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
365 ; ------------------------------------------------------------------------
366 ; This is the program code after setup. It starts at $400
376 ; Push arguments and call main()
380 ; Call module destructors. This is also the _exit entry.
382 _exit: jsr donelib ; Run module destructors
384 ; We need access to the system bank now
389 ; Switch back the video to the system bank
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
414 ; Setup the welcome code at the stack bottom in the system bank. Use
415 ; the F4/F5 vector to access the system bank
428 ; ------------------------------------------------------------------------
429 ; Code that is copied into the system bank at $100 when switching back
432 jmp $8000 ; BASIC cold start
433 reset_size = * - reset
435 ; ------------------------------------------------------------------------
436 ; Code for a few simpler kernal calls goes here
492 ; -------------------------------------------------------------------------
493 ; Data area - switch back to relocatable mode