;
; Startup code for cc65 (CBM 600/700 version)
-;
-; This must be the *first* file on the linker command line
;
- .export _exit, BRKVec, UDTIM
+ .export _exit, BRKVec
+ .export __STARTUP__ : absolute = 1 ; Mark as startup
- .import condes, initlib, donelib
+ .import callirq_y, initlib, donelib
.import push0, callmain
.import __BSS_RUN__, __BSS_SIZE__, __EXTZP_RUN__
- .import __IRQFUNC_TABLE__, __IRQFUNC_COUNT__
- .import SCNKEY
+ .import __INTERRUPTOR_COUNT__
+ .import scnkey, UDTIM
.include "zeropage.inc"
.include "extzp.inc"
; 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 $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.
+
+.SEGMENT "PAGE2"
+
+.proc transfer_table
+
+ .byte $9F, DEVNUM
+ .byte $CA, CURS_Y
+ .byte $CB, CURS_X
+ .byte $CC, graphmode
+ .byte $D4, config
+
+.endproc
+
+
+;------------------------------------------------------------------------------
+; 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.
+
+.segment "PAGE3"
+
+BRKVec: .addr _exit ; BRK indirect vector
+
+.proc callbank15
+
+ excrts = $FF05
+
+.org $FECB
+
+entry: php
+ pha
+ lda #$0F ; Bank 15
+ sta IndReg
+ txa
+ pha
+ tya
+ pha
+ sei
+ ldy #$FF
+ lda (sysp1),y
+ tay
+ lda ExecReg
+ sta (sysp1),y
+ dey
+
+ lda #.hibyte(excrts-1)
+ sta (sysp1),y
+ dey
+ lda #.lobyte(excrts-1)
+ sta (sysp1),y
+
+ tya
+ sec
+ sbc #7
+ sta $1FF ; Save new sp
+ tay
+
+ tsx
+
+ pla
+ iny
+ sta (sysp1),y
+ pla
+ iny
+ sta (sysp1),y
+ pla
+ iny
+ sta (sysp1),y
+ pla
+ iny
+ sta (sysp1),y
+
+ lda $105,x
+ sec
+ sbc #3
+ iny
+ sta (sysp1),y
+ lda $106,x
+ sbc #0
+ iny
+ sta (sysp1),y
+
+ ldy $1FF ; Restore sp in bank 15
+
+ lda #.hibyte(expull-1)
+ sta (sysp1),y
+ dey
+ lda #.lobyte(expull-1)
+ sta (sysp1),y
+ dey
+ pla
+ pla
+ tsx
+ stx $1FF
+ tya
+ tax
+ txs
+ lda IndReg
+ jmp $FFF6
+
+expull: pla
+ tay
+ pla
+ tax
+ pla
+ plp
+ rts
+
+.if (expull <> $FF2E)
+.error "Symbol expull must be aligned with kernal in bank 15"
+.endif
+
+.reloc
+
+.endproc
+
;------------------------------------------------------------------------------
; 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
.segment "STARTUP"
-Back: sei
- ldx spsave
- txs
- lda IndReg
- 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:
jmp Origin
-; Hardware vectors, copied to $FFFA
+; Hardware vectors, copied to $FFF6
.proc vectors
sta ExecReg
.word $eb49 ; ktab4
.endproc
-; The following code is part of the kernal call subroutine. It is copied
-; to $FFAE
-
-.proc callsysbank_15
- php
- pha
- lda #$0F ; Bank 15
- sta IndReg
- sei
-.endproc
-
-; Save the old stack pointer from the system bank and setup our hw sp
+; Switch the indirect segment to the system bank
-Origin: tsx
- stx spsave ; Save the system stackpointer
- ldx #$FE ; Leave $1FF untouched for cross bank calls
- txs ; Set up our own stack
+Origin: lda #$0F
+ sta IndReg
; Initialize the extended zeropage
dex
bpl L1
-; Set the interrupt, NMI and other vectors
+; Save the old stack pointer from the system bank and setup 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
- ldy #.sizeof(vectors)-1
-L2: lda vectors,y
- sta $10000 - .sizeof(vectors),y
- dey
- bpl L2
+; Copy stuff from the system zeropage to ours
-; Switch the indirect segment to the system bank
+ lda #.sizeof(transfer_table)
+ sta ktmp
+L2: ldx ktmp
+ ldy transfer_table-2,x
+ lda transfer_table-1,x
+ tax
+ lda (sysp0),y
+ sta $00,x
+ dec ktmp
+ dec ktmp
+ bne L2
- lda #$0F
- sta IndReg
+; Set the interrupt, NMI and other vectors
+
+ ldx #.sizeof(vectors)-1
+L3: lda vectors,x
+ sta $10000 - .sizeof(vectors),x
+ dex
+ bpl L3
; Setup the C stack
- lda #.lobyte($FEB5 - .sizeof(callsysbank_15))
- sta sp
- lda #.hibyte($FEB5 - .sizeof(callsysbank_15))
+ 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
-; the system bank. Copy the bank switch routines starting at $FEB5 from the
-; system bank into the current bank.
-
+; the system bank.
- ldy #.sizeof(callsysbank_15)-1 ; Copy the modified part
-@L1: lda callsysbank_15,y
- sta $FEB5 - .sizeof(callsysbank_15),y
+ ldy #.sizeof(callbank15)
+@L1: lda callbank15-1,y
+ sta callbank15::entry-1,y
dey
- bpl @L1
-
- lda #.lobyte($FEB5) ; Copy the ROM part
- sta ptr1
- lda #.hibyte($FEB5)
- sta ptr1+1
- ldy #$00
-@L2: lda (ptr1),y
- sta $FEB5,y
- iny
- cpy #<($FF6F-$FEB5)
- bne @L2
+ bne @L1
-; Setup the jump vector table
+; Setup the jump vector table. Y is zero on entry.
- ldy #$00
ldx #45-1 ; Number of vectors
-@L3: lda #$20 ; JSR opcode
+@L2: lda #$20 ; JSR opcode
sta $FF6F,y
iny
- lda #.lobyte($FEB5 - .sizeof(callsysbank_15))
+ lda #.lobyte(callbank15::entry)
sta $FF6F,y
iny
- lda #.hibyte($FEB5 - .sizeof(callsysbank_15))
+ lda #.hibyte(callbank15::entry)
sta $FF6F,y
iny
dex
- bpl @L3
-
-; Copy the stack from the system bank into page 3
-
- ldy #$FF
-L4: lda (sysp1),y
- sta $300,y
- dey
- cpy spsave
- bne L4
+ bpl @L2
; Set the indirect segment to bank we're executing in
- lda ExecReg
+ lda ExecReg
sta IndReg
; Zero the BSS segment. We will do that here instead calling the routine
iny
bne Z1
inc ptr1+1 ; Next page
- dex
+ dex
bne Z1
; Clear the remaining page
.segment "PAGE2"
-; Call module constructors, enable chained IRQs afterwards.
+; Activate 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()
jsr callmain
-; Disable Call module destructors. This is also the _exit entry and the default entry
+; Call module destructors. This is also the _exit entry and the default entry
; point for the break vector.
-_exit: lda #$00
- sta irqcount ; Disable custom irq handlers
+_exit: pha ; Save the return code
jsr donelib ; Run module destructors
+ lda #$00
+ sta irqcount ; Disable custom irq handlers
-; Adress the system bank
+; Address the system bank
lda #$0F
sta IndReg
-; Copy back the old system bank stack contents
+; Copy stuff back from our zeropage to the systems
- ldy #$FF
-@L1: lda $300,y
- sta (sysp1),y
- dey
- cpy spsave
- bne @L1
+.if 0
+ lda #.sizeof(transfer_table)
+ sta ktmp
+@L0: ldx ktmp
+ ldy transfer_table-2,x
+ lda transfer_table-1,x
+ tax
+ lda $00,x
+ sta (sysp0),y
+ dec ktmp
+ dec ktmp
+ bne @L0
+.endif
+
+; Place the program return code into ST
+
+ pla
+ ldy #$9C ; ST
+ sta (sysp0),y
; Setup the welcome code at the stack bottom in the system bank.
- ldy #$00
+ ldy #$FF
+ lda (sysp1),y ; Load system bank sp
+ tax
+ iny ; Y = 0
lda #$58 ; CLI opcode
sta (sysp1),y
iny
lda #$60 ; RTS opcode
sta (sysp1),y
+ lda IndReg
+ sei
+ txs
jmp Back
; -------------------------------------------------------------------------
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
+ lda $105,x ; Get the flags from the stack
+ and #$10 ; Test break flag
bne dobrk
; It's an IRQ
ldy irqcount
beq irqskip
- lda #<__IRQFUNC_TABLE__
- ldx #>__IRQFUNC_TABLE__
- jsr condes ; Call the functions
+ jsr callirq_y ; Call the functions
; Done with chained IRQ handlers, check the TPI for IRQs and handle them
cmp #%00000001 ; ticker irq?
bne irqend
- jsr SCNKEY ; Poll the keyboard
+ jsr scnkey ; Poll the keyboard
jsr UDTIM ; Bump the time
; Done
dobrk: jmp (BRKVec)
-; -------------------------------------------------------------------------
-; udtim routine for the 610. We will not check for the stop key here, since
-; C programs will not use it.
-;
-
-.proc UDTIM
-
- inc time
- bne L9
- inc time+1
- bne L9
- inc time+2
- bne L9
- inc time+3
-L9: rts
-
-.endproc
-
-; -------------------------------------------------------------------------
-; Page 3
-
-.segment "PAGE3"
-
-BRKVec: .addr _exit ; BRK indirect vector
-
-
; -------------------------------------------------------------------------
; Data area.
-.data
-spsave: .res 1
-
.bss
irqcount: .byte 0