;
; Startup code for cc65 (CBM 600/700 version)
-;
-; This must be the *first* file on the linker command line
;
.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 __INTERRUPTOR_COUNT__
.import scnkey, UDTIM
.include "zeropage.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
.proc transfer_table
+ .byte $9F, DEVNUM
.byte $CA, CURS_Y
.byte $CB, CURS_X
.byte $CC, graphmode
.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
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
-
-Origin: tsx
- stx spsave ; Save the system stackpointer
- ldx #$FE ; Leave $1FF untouched for cross bank calls
- txs ; Set up our own stack
-
; Switch the indirect segment to the system bank
- lda #$0F
+Origin: lda #$0F
sta IndReg
; Initialize the extended zeropage
dex
bpl L1
+; 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
+
; Copy stuff from the system zeropage to ours
lda #.sizeof(transfer_table)
; Setup the C stack
- lda #.lobyte($FEB5 - .sizeof(callsysbank_15))
+ lda #.lobyte(callbank15::entry)
sta sp
- lda #.hibyte($FEB5 - .sizeof(callsysbank_15))
+ 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
.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()
; 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
; Address the system bank
bne @L0
.endif
-; Copy back the old system bank stack contents
+; Place the program return code into ST
- ldy #$FF
-@L1: lda $300,y
- sta (sysp1),y
- dey
- cpy spsave
- bne @L1
+ 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
dobrk: jmp (BRKVec)
-; -------------------------------------------------------------------------
-; Page 3
-
-.segment "PAGE3"
-
-BRKVec: .addr _exit ; BRK indirect vector
-
-
; -------------------------------------------------------------------------
; Data area.
-.data
-spsave: .res 1
-
.bss
irqcount: .byte 0