;
; Startup code for cc65 (CBM 600/700 version)
-;
-; This must be the *first* file on the linker command line
;
- .export _exit, BRKVec
+ .export _exit, BRKVec
+ .export __STARTUP__ : absolute = 1 ; Mark as startup
- .import callirq_y, initlib, donelib
- .import push0, callmain
- .import __BSS_RUN__, __BSS_SIZE__, __EXTZP_RUN__
- .import __IRQFUNC_COUNT__
- .import scnkey, UDTIM
+ .import callirq_y, initlib, donelib
+ .import push0, callmain
+ .import __BSS_RUN__, __BSS_SIZE__, __EXTZP_RUN__
+ .import __INTERRUPTOR_COUNT__
+ .import scnkey, UDTIM
- .include "zeropage.inc"
+ .include "zeropage.inc"
.include "extzp.inc"
- .include "cbm610.inc"
+ .include "cbm610.inc"
; ------------------------------------------------------------------------
-; BASIC header and a small BASIC program. Since it is not possible to start
+; The BASIC header and a small BASIC program. Since it isn't possible to start
; programs in other banks using SYS, the BASIC program will write a small
-; machine code program into memory at $100 and start that machine code
+; machine code program into memory at $100; and, start that machine code
; program. The machine code program will then start the machine language
; code in bank 1, which will initialize the system by copying stuff from
; the system bank, and start the application.
;
-; Here's the basic program that's in the following lines:
+; Here's the BASIC program that's in the following lines:
;
; 10 for i=0 to 4
; 20 read j
; The machine program in the data lines is:
;
; sei
-; lda #$01
-; sta $00 <-- Switch to bank 1 after this command
+; lda #$01
+; sta $00 <-- Switch to bank 1 after this command
;
-; Initialization is not only complex because of the jumping from one bank
-; into another. but also because we want to save memory, and because of
-; this, we will use the system memory ($00-$3FF) for initialization stuff
+; Initialization is complex not only because of the jumping from one bank
+; into another. but also because we want to save memory; and because of
+; that, we will use the system memory ($00-$3FF) for initialization stuff
; that is overwritten later.
;
-.segment "BASICHDR"
+.segment "EXEHDR"
- .byte $03,$00,$11,$00,$0a,$00,$81,$20,$49,$b2,$30,$20,$a4,$20,$34,$00
- .byte $19,$00,$14,$00,$87,$20,$4a,$00,$27,$00,$1e,$00,$97,$20,$32,$35
- .byte $36,$aa,$49,$2c,$4a,$00,$2f,$00,$28,$00,$82,$20,$49,$00,$39,$00
- .byte $32,$00,$9e,$20,$32,$35,$36,$00,$4f,$00,$3c,$00,$83,$20,$31,$32
- .byte $30,$2c,$31,$36,$39,$2c,$31,$2c,$31,$33,$33,$2c,$30,$00,$00,$00
+ .byte $03,$00,$11,$00,$0a,$00,$81,$20,$49,$b2,$30,$20,$a4,$20,$34,$00
+ .byte $19,$00,$14,$00,$87,$20,$4a,$00,$27,$00,$1e,$00,$97,$20,$32,$35
+ .byte $36,$aa,$49,$2c,$4a,$00,$2f,$00,$28,$00,$82,$20,$49,$00,$39,$00
+ .byte $32,$00,$9e,$20,$32,$35,$36,$00,$4f,$00,$3c,$00,$83,$20,$31,$32
+ .byte $30,$2c,$31,$36,$39,$2c,$31,$2c,$31,$33,$33,$2c,$30,$00,$00,$00
;------------------------------------------------------------------------------
-; A table that contains values that must be transfered from the system zero
-; page into out zero page. Contains pairs of bytes, first one is the address
-; in the system ZP, second one is our ZP address. The table goes into page 2,
-; but is declared here, because it is needed earlier.
+; A table that contains values that must be transferred from the system zero-
+; page into our zero-page. Contains pairs of bytes, first one is the address
+; in the system ZP, second one is our ZP address. The table goes into page 2;
+; but, is declared here because it is needed earlier.
.SEGMENT "PAGE2"
+; (We use .proc because we need both a label and a scope.)
+
.proc transfer_table
+ .byte $9F, DEVNUM
.byte $CA, CURS_Y
.byte $CB, CURS_X
.byte $CC, graphmode
; Page 3 data. This page contains the break vector and the bankswitch
; subroutine that is copied into high memory on startup. The space occupied by
; this routine will later be used for a copy of the bank 15 stack. It must be
-; saved, since we're going to destroy it when calling bank 15.
+; saved since we're going to destroy it when calling bank 15.
.segment "PAGE3"
.proc callbank15
- excrts = $FF05
+ excrts := $FF05 ; In bank 15 ROM
.org $FECB
entry: php
pha
- lda #$0F ; Bank 15
+ lda #$0F ; Bank 15
sta IndReg
txa
pha
tya
sec
sbc #7
- sta $1FF ; Save new sp
+ sta $1FF ; Save new sp
tay
tsx
iny
sta (sysp1),y
- ldy $1FF ; Restore sp in bank 15
+ ldy $1FF ; Restore sp in bank 15
lda #.hibyte(expull-1)
sta (sysp1),y
rts
.if (expull <> $FF2E)
-.error "Symbol expull must be aligned with kernal in bank 15"
+.error "Symbol expull must be aligned with Kernal in bank 15"
.endif
.reloc
;------------------------------------------------------------------------------
; The code in the target bank when switching back will be put at the bottom
; of the stack. We will jump here to switch segments. The range $F2..$FF is
-; not used by any kernal routine.
+; not used by any Kernal routine.
.segment "STARTUP"
-Back: sta ExecReg
+Back: sta ExecReg
; We are at $100 now. The following snippet is a copy of the code that is poked
-; in the system bank memory by the basic header program, it's only for
-; documentation and not actually used here:
+; in the system bank memory by the BASIC header program; it's only for
+; documentation, and not actually used here:
- sei
- lda #$01
- sta ExecReg
+ sei
+ lda #$01
+ sta ExecReg
; This is the actual starting point of our code after switching banks for
; startup. Beware: The following code will get overwritten as soon as we
-; use the stack (since it's in page 1)! We jump to another location, since
+; use the stack (since it's in page 1)! We jump to another location since
; we need some space for subroutines that aren't used later.
jmp Origin
sta ExecReg
rts
nop
- .word nmi ; NMI vector
- .word 0 ; Reset - not used
- .word irq ; IRQ vector
+ .word nmi ; NMI vector
+ .word 0 ; Reset -- not used
+ .word irq ; IRQ vector
.endproc
-; Initializers for the extended zeropage. See extzp.s
+; Initializers for the extended zero-page. See "extzp.s".
.proc extzp
.word $0100 ; sysp1
.word $0300 ; sysp3
- .word $d800 ; crtc
- .word $da00 ; sid
- .word $db00 ; ipccia
- .word $dc00 ; cia
- .word $dd00 ; acia
- .word $de00 ; tpi1
- .word $df00 ; tpi2
- .word $ea29 ; ktab1
- .word $ea89 ; ktab2
- .word $eae9 ; ktab3
- .word $eb49 ; ktab4
+ .word $d800 ; crtc
+ .word $da00 ; sid
+ .word $db00 ; ipccia
+ .word $dc00 ; cia
+ .word $dd00 ; acia
+ .word $de00 ; tpi1
+ .word $df00 ; tpi2
+ .word $ea29 ; ktab1
+ .word $ea89 ; ktab2
+ .word $eae9 ; ktab3
+ .word $eb49 ; ktab4
.endproc
-; Switch the indirect segment to the system bank
+; Switch the indirect segment to the system bank.
-Origin: lda #$0F
- sta IndReg
+Origin: lda #$0F
+ sta IndReg
-; Initialize the extended zeropage
+; Initialize the extended zero-page.
ldx #.sizeof(extzp)-1
L1: lda extzp,x
dex
bpl L1
-; Save the old stack pointer from the system bank and setup our hw sp
+; Save the old stack pointer from the system bank; and, set up our hw sp.
tsx
txa
ldy #$FF
sta (sysp1),y ; Save system stack point into $F:$1FF
- ldx #$FE ; Leave $1FF untouched for cross bank calls
- txs ; Set up our own stack
+ ldx #$FE ; Leave $1FF untouched for cross-bank calls
+ txs ; Set up our own stack
-; Copy stuff from the system zeropage to ours
+; Copy stuff from the system zero-page to ours.
lda #.sizeof(transfer_table)
sta ktmp
dec ktmp
bne L2
-; Set the interrupt, NMI and other vectors
+; Set the interrupt, NMI, and other vectors.
- ldx #.sizeof(vectors)-1
-L3: lda vectors,x
- sta $10000 - .sizeof(vectors),x
- dex
- bpl L3
+ ldx #.sizeof(vectors)-1
+L3: lda vectors,x
+ sta $10000 - .sizeof(vectors),x
+ dex
+ bpl L3
-; Setup the C stack
+; Set up the C stack.
- lda #.lobyte(callbank15::entry)
- sta sp
- lda #.hibyte(callbank15::entry)
- sta sp+1
+ lda #.lobyte(callbank15::entry)
+ sta sp
+ lda #.hibyte(callbank15::entry)
+ sta sp+1
-; Setup the subroutine and jump vector table that redirects kernal calls to
+; Set up the subroutine and jump vector table that redirects Kernal calls to
; the system bank.
ldy #.sizeof(callbank15)
dey
bne @L1
-; Setup the jump vector table. Y is zero on entry.
+; Set up the jump vector table. Y is zero on entry.
- ldx #45-1 ; Number of vectors
-@L2: lda #$20 ; JSR opcode
+ ldx #45-1 ; Number of vectors
+@L2: lda #$20 ; JSR opcode
sta $FF6F,y
iny
lda #.lobyte(callbank15::entry)
dex
bpl @L2
-; Set the indirect segment to bank we're executing in
+; Set the indirect segment to the bank that we're executing in.
- lda ExecReg
- sta IndReg
+ lda ExecReg
+ sta IndReg
-; Zero the BSS segment. We will do that here instead calling the routine
-; in the common library, since we have the memory anyway, and this way,
+; Zero the BSS segment. We will do that here instead of calling the routine
+; in the common library, since we have the memory anyway; and this way,
; it's reused later.
- lda #<__BSS_RUN__
- sta ptr1
- lda #>__BSS_RUN__
- sta ptr1+1
- lda #0
- tay
-
-; Clear full pages
-
- ldx #>__BSS_SIZE__
- beq Z2
-Z1: sta (ptr1),y
- iny
- bne Z1
- inc ptr1+1 ; Next page
- dex
- bne Z1
-
-; Clear the remaining page
-
-Z2: ldx #<__BSS_SIZE__
- beq Z4
-Z3: sta (ptr1),y
- iny
- dex
- bne Z3
+ lda #<__BSS_RUN__
+ sta ptr1
+ lda #>__BSS_RUN__
+ sta ptr1+1
+ lda #0
+ tay
+
+; Clear full pages.
+
+ ldx #>__BSS_SIZE__
+ beq Z2
+Z1: sta (ptr1),y
+ iny
+ bne Z1
+ inc ptr1+1 ; Next page
+ dex
+ bne Z1
+
+; Clear the remaining page.
+
+Z2: ldx #<__BSS_SIZE__
+ beq Z4
+Z3: sta (ptr1),y
+ iny
+ dex
+ bne Z3
Z4: jmp Init
; ------------------------------------------------------------------------
-; We are at $200 now. We may now start calling subroutines safely, since
+; We are at $200 now. We may now start calling subroutines safely since
; the code we execute is no longer in the stack page.
.segment "PAGE2"
-; Call module constructors, enable chained IRQs afterwards.
+; Activate the chained interrupt handlers; then, enable interrupts.
-Init: jsr initlib
- lda #.lobyte(__IRQFUNC_COUNT__*2)
+Init: lda #.lobyte(__INTERRUPTOR_COUNT__*2)
sta irqcount
+ cli
-; Enable interrupts
+; Call module constructors.
- cli
+ jsr initlib
-; Push arguments and call main()
+; Push the command-line arguments; and, call main().
- jsr callmain
+ jsr callmain
-; Call module destructors. This is also the _exit entry and the default entry
+; Call the module destructors. This is also the exit() entry and the default entry
; point for the break vector.
-_exit: pha ; Save the return code
- lda #$00
+_exit: pha ; Save the return code
+ jsr donelib ; Run module destructors
+ lda #$00
sta irqcount ; Disable custom irq handlers
- jsr donelib ; Run module destructors
-; Address the system bank
+; Address the system bank.
lda #$0F
sta IndReg
-; Copy stuff back from our zeropage to the systems
+; Copy stuff back from our zero-page to the system's.
.if 0
lda #.sizeof(transfer_table)
bne @L0
.endif
-; Place the program return code into ST
+; Place the program return code into BASIC's status variable.
- pla
- ldy #$9C ; ST
- sta (sysp0),y
+ pla
+ ldy #$9C ; ST
+ sta (sysp0),y
-; Setup the welcome code at the stack bottom in the system bank.
+; Set up the welcome code at the stack bottom in the system bank.
ldy #$FF
lda (sysp1),y ; Load system bank sp
iny
lda #$60 ; RTS opcode
sta (sysp1),y
- lda IndReg
+ lda IndReg
sei
- txs
+ txs
jmp Back
; -------------------------------------------------------------------------
; easier chaining, we do handle the IRQs in the execution bank (instead of
; passing them to the system bank).
-; This is the mapping of the active irq register of the 6525 (tpi1):
+; This is the mapping of the active IRQ register of the 6525 (tpi1):
;
; Bit 7 6 5 4 3 2 1 0
-; | | | | ^ 50 Hz
+; | | | | ^ 50 Hz.
; | | | ^ SRQ IEEE 488
-; | | ^ cia
+; | | ^ CIA
; | ^ IRQB ext. Port
-; ^ acia
+; ^ ACIA
irq: pha
txa
lda IndReg
pha
lda ExecReg
- sta IndReg ; Be sure to address our segment
- tsx
- lda $105,x ; Get the flags from the stack
- and #$10 ; Test break flag
- bne dobrk
+ sta IndReg ; Be sure to address our segment
+ tsx
+ lda $105,x ; Get the flags from the stack
+ and #$10 ; Test break flag
+ bne dobrk
-; It's an IRQ
+; It's an IRQ.
cld
-; Call chained IRQ handlers
+; Call the chained IRQ handlers.
- ldy irqcount
+ ldy irqcount
beq irqskip
- jsr callirq_y ; Call the functions
+ jsr callirq_y ; Call the functions
-; Done with chained IRQ handlers, check the TPI for IRQs and handle them
+; Done with the chained IRQ handlers; check the TPI for IRQs, and handle them.
-irqskip:lda #$0F
- sta IndReg
- ldy #TPI::AIR
- lda (tpi1),y ; Interrupt Register 6525
- beq noirq
+irqskip:lda #$0F
+ sta IndReg
+ ldy #TPI::AIR
+ lda (tpi1),y ; Interrupt Register 6525
+ beq noirq
-; 50/60Hz interrupt
+; 50/60Hz. interrupt
- cmp #%00000001 ; ticker irq?
- bne irqend
- jsr scnkey ; Poll the keyboard
- jsr UDTIM ; Bump the time
+ cmp #%00000001 ; ticker IRQ?
+ bne irqend
+ jsr scnkey ; Poll the keyboard
+ jsr UDTIM ; Bump the time
-; Done
+; Done.
-irqend: ldy #TPI::AIR
- sta (tpi1),y ; Clear interrupt
+irqend: ldy #TPI::AIR
+ sta (tpi1),y ; Clear interrupt
-noirq: pla
+noirq: pla
sta IndReg
pla
tay
pla
tax
pla
-nmi: rti
+nmi: rti
-dobrk: jmp (BRKVec)
+dobrk: jmp (BRKVec)
; -------------------------------------------------------------------------
-; Data area.
+; Data area
.bss
irqcount: .byte 0
-