2 ; Startup code for cc65 (CBM 500 version)
4 ; This must be the *first* file on the linker command line
8 .import _clrscr, initlib, donelib
10 .import __BSS_RUN__, __BSS_SIZE__
12 .import k_irq, k_nmi, k_plot, k_udtim, k_scnkey
14 .include "zeropage.inc"
18 ; ------------------------------------------------------------------------
19 ; Define and export the ZP variables for the CBM510 runtime
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
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
42 regbank: .res 6 ; 6 byte register bank
44 zpspace = * - zpstart ; Zero page space allocated
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.
56 ; Here's the basic program that's in the following lines:
63 ; 60 data 120,169,0,133,0
65 ; The machine program in the data lines is:
69 ; sta $00 <-- Switch to bank 0 after this command
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.
77 ; To make things more simple, make the code of this module absolute.
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
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:
103 RecvBuf: .word $0100 ; RS232 received buffer
104 SendBuf: .word $0200 ; RS232 send buffer
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.
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:
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)!
130 stx spsave ; Save the system stackpointer
132 txs ; Set up our own stack
134 ; Set the interrupt, NMI and other vectors
142 ; Switch the indirect segment to the system bank
147 ; Copy the kernal zero page ($90-$F2) from the system bank
159 ; Copy the page 3 vectors in place
168 ; Copy the rest of page 3 from the system bank
179 ; Set the indirect segment to bank we're executing in
184 ; Zero the BSS segment. We will do that here instead calling the routine
185 ; in the common library, since we have the memory anyway, and this way,
202 inc ptr1+1 ; Next page
206 ; Clear the remaining page
208 Z2: ldx #<__BSS_SIZE__
223 ; We expect to be in page 2 now
233 .error "Code range invalid"
236 ; This code is in page 2, so we may now start calling subroutines safely,
237 ; since the code we execute is no longer in the stack page.
239 ; Clear the video memory. We will do this before switching the video to bank 0
240 ; to avoid garbage when doing so.
244 ; Reprogram the VIC so that the text screen is at $F800 in the execution bank
245 ; This is done in three steps:
247 lda #$0F ; We need access to the system bank
250 ; Place the VIC video RAM into bank 0
260 ; Set bit 14/15 of the VIC address range to the high bits of VIDEO_RAM
261 ; PC6/PC7 (VICBANKSEL 0/1) = 11
267 ora #((>VIDEO_RAM) & $C0)
270 ; Set bits 10-13 of the VIC address range to address F800
276 ora #(((>VIDEO_RAM) & $3F) << 2)
279 ; Switch back to the execution bank
284 ; Call module constructors
288 ; Create the (empty) command line for the program
293 ; Execute the program code
297 ; ------------------------------------------------------------------------
298 ; Additional data that we need for initialization and that's overwritten
312 jmp k_scnkey ; SCNKEY
321 jmp k_setlfs ; SETLFS
322 jmp k_setnam ; SETNAM
332 jmp k_settim ; SETTIM
338 jmp k_screen ; SCREEN
340 jmp k_iobase ; IOBASE
345 .word 0 ; Reset - not used
347 vectable_size = * - vectable
350 .word k_irq ; IRQ user vector
351 .word k_brk ; BRK user vector
352 .word k_nmi ; NMI user vector
353 p3vectable_size = * - p3vectable
356 ; ------------------------------------------------------------------------
357 ; This is the program code after setup. It starts at $400
369 ldy #4 ; Argument size
370 jsr _main ; call the users code
372 ; Call module destructors. This is also the _exit entry.
374 _exit: jsr donelib ; Run module destructors
376 ; We need access to the system bank now
381 ; Switch back the video to the system bank
395 ; Clear the start of the zero page, since it will be interpreted as a
396 ; (garbage) BASIC program otherwise. This is also the default entry for
406 ; Setup the welcome code at the stack bottom in the system bank. Use
407 ; the F4/F5 vector to access the system bank
420 ; ------------------------------------------------------------------------
421 ; Code that is copied into the system bank at $100 when switching back
424 jmp $8000 ; BASIC cold start
425 reset_size = * - reset
427 ; ------------------------------------------------------------------------
428 ; Code for a few simpler kernal calls goes here
472 ; -------------------------------------------------------------------------
473 ; Data area - switch back to relocatable mode