]> git.sur5r.net Git - cc65/blobdiff - libsrc/cbm510/crt0.s
remove superfluous ".code" line
[cc65] / libsrc / cbm510 / crt0.s
index 6500397ae72e77375ab74acfb5dc612b0cff1cf9..ef2cb8c6295a8256597c2016d1e5dc6c2bc03e1b 100644 (file)
@@ -1,22 +1,20 @@
 ;
 ; Startup code for cc65 (CBM 500 version)
-;
-; This must be the *first* file on the linker command line
 ;
 
        .export         _exit
-       .exportzp       vic, sid, cia1, cia2, acia, tpi1, tpi2, ktab1
-       .exportzp       ktab2, ktab3, ktab4, time, RecvBuf, SendBuf
+        .export         __STARTUP__ : absolute = 1      ; Mark as startup
 
-       .import         _clrscr, initlib, donelib
-       .import         push0, _main
+       .import         _clrscr, initlib, donelib, callirq_y
+       .import         push0, callmain
        .import         __CHARRAM_START__, __CHARRAM_SIZE__, __VIDRAM_START__
-       .import         __BSS_RUN__, __BSS_SIZE__
-       .import         irq, nmi
-               .import         k_irq, k_nmi, k_plot, k_udtim, k_scnkey
+       .import         __BSS_RUN__, __BSS_SIZE__, __EXTZP_RUN__
+       .import         __INTERRUPTOR_COUNT__
+       .import         scnkey, UDTIM
 
        .include        "zeropage.inc"
-       .include        "cbm510.inc"
+        .include        "extzp.inc"
+       .include        "cbm510.inc"
 
 
 ; ------------------------------------------------------------------------
 ; that is overwritten later.
 ;
 
-.code
-
-; To make things more simple, make the code of this module absolute.
+.segment        "BASICHDR"
 
-       .org    $0001
-Head:  .byte   $03,$00,$11,$00,$0a,$00,$81,$20,$49,$b2,$30,$20,$a4,$20,$34,$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,$30,$2c,$31,$33,$33,$2c,$30,$00,$00,$00
 
-; Since we need some vectors to access stuff in the system bank for our own,
-; we will include them here, starting from $60:
+;------------------------------------------------------------------------------
+; 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   $CA, CURS_Y
+        .byte   $CB, CURS_X
+        .byte   $EC, CHARCOLOR
+
+.endproc
 
-       .res    $60-*
 
-vic:           .word   $d800
-sid:           .word   $da00
-cia1:          .word   $db00
-cia2:                  .word   $dc00
-acia:                  .word   $dd00
-tpi1:          .word   $de00
-tpi2:                  .word   $df00
-ktab1:         .word   $eab1
-ktab2:         .word   $eb11
-ktab3:         .word   $eb71
-ktab4:         .word   $ebd1
-time:          .dword  $0000
-RecvBuf:       .word   $0100           ; RS232 received buffer
-SendBuf:       .word   $0200           ; RS232 send buffer
+;------------------------------------------------------------------------------
+; 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  = $FEFE
+
+.org    $FEC3
+
+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 <> $FF26)
+.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
 ; not used by any kernal routine.
 
-       .res    $F8-*
-Back:  ldx     spsave
-       txs
-       lda     IndReg
-       sta     ExecReg
+.segment        "STARTUP"
 
-; The following code 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:
+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:
 
        sei
        lda     #$00
@@ -100,62 +193,119 @@ Back:    ldx     spsave
 
 ; 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)!
+; 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.
 
-       tsx
-               stx     spsave          ; Save the system stackpointer
-       ldx     #$FF
-       txs                     ; Set up our own stack
+        jmp     Origin
 
-; Set the interrupt, NMI and other vectors
+; Hardware vectors, copied to $FFFA
 
-       ldy     #vectable_size
-L0:    lda     vectable-1,y
-       sta     $FF80,y
-       dey
-               bne     L0
+.proc   vectors
+        sta     ExecReg
+        rts
+        nop
+               .word   nmi             ; NMI vector
+               .word   0               ; Reset - not used
+               .word   irq             ; IRQ vector
+.endproc
+
+; Initializers for the extended zeropage. See extzp.s
+
+.proc   extzp
+        .word   $0100           ; sysp1
+        .word   $0300           ; sysp3
+        .word          $d800           ; vic
+       .word   $da00           ; sid
+       .word   $db00           ; cia1
+       .word   $dc00           ; cia2
+       .word   $dd00           ; acia
+       .word   $de00           ; tpi1
+       .word   $df00           ; tpi2
+       .word   $eab1           ; ktab1
+       .word   $eb11           ; ktab2
+       .word   $eb71           ; ktab3
+       .word   $ebd1           ; ktab4
+.endproc
 
 ; Switch the indirect segment to the system bank
 
-       lda     #$0F
+Origin: lda    #$0F
        sta     IndReg
 
-; Copy the kernal zero page ($90-$F2) from the system bank
+; Initialize the extended zeropage
+
+        ldx     #.sizeof(extzp)-1
+L1:     lda     extzp,x
+        sta     <__EXTZP_RUN__,x
+        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)
+        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     #$90
-       sta     ptr1
-       lda     #$00
-       sta     ptr1+1
-       ldy     #$62-1
-L1:    lda     (ptr1),y
-       sta     $90,y
-       dey
-       bpl     L1
+; Set the interrupt, NMI and other vectors
 
-; Copy the page 3 vectors in place
+       ldx     #.sizeof(vectors)-1
+L3:            lda     vectors,x
+       sta     $10000 - .sizeof(vectors),x
+       dex
+               bpl     L3
 
-       ldy     #$00
-L2:    lda     p3vectable,y
-       sta     $300,y
-       iny
-       cpy     #p3vectable_size
-               bne     L2
+; Setup the C stack
 
-; Copy the rest of page 3 from the system bank
-
-       lda     #$00
-       sta     ptr1
-       lda     #$03
-       sta     ptr1+1
-L3:    lda     (ptr1),y
-       sta     $300,y
-       iny
-       bne     L3
+       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.
+
+        ldy     #.sizeof(callbank15)
+@L1:    lda     callbank15-1,y
+        sta     callbank15::entry-1,y
+        dey
+        bne     @L1
+
+; Setup the jump vector table. Y is zero on entry.
+
+        ldx     #45-1                   ; Number of vectors
+@L2:    lda     #$20                    ; JSR opcode
+        sta     $FF6F,y
+        iny
+        lda     #.lobyte(callbank15::entry)
+        sta     $FF6F,y
+        iny
+        lda     #.hibyte(callbank15::entry)
+        sta     $FF6F,y
+        iny
+        dex
+        bpl     @L2
 
 ; Set the indirect segment to bank 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,
@@ -176,7 +326,7 @@ Z1: sta     (ptr1),y
        iny
        bne     Z1
        inc     ptr1+1                  ; Next page
-       dex
+       dex
        bne     Z1
 
 ; Clear the remaining page
@@ -187,34 +337,17 @@ Z3:       sta     (ptr1),y
        iny
        dex
        bne     Z3
-Z4:
-
-; Setup the C stack
+Z4:     jmp     Init
 
-       lda     #<$FF81
-       sta     sp
-               lda     #>$FF81
-       sta     sp+1
-
-; We expect to be in page 2 now
-
-.if    (* < $1FD)
-       jmp     $200
-       .res    $200-*
-.endif
-.if    (* < $200)
-       .res    $200-*,$EA
-.endif
-.if            (* >= $2F0)
-.error "Code range invalid"
-.endif
+; ------------------------------------------------------------------------
+; We are at $200 now. We may now start calling subroutines safely, since
+; the code we execute is no longer in the stack page.
 
-; This code is in page 2, so we may now start calling subroutines safely,
-; since the code we execute is no longer in the stack page.
+.segment        "PAGE2"
 
 ; Copy the character rom from the system bank into the execution bank
 
-        lda     #<$C000
+Init:   lda     #<$C000
        sta     ptr1
        lda     #>$C000
        sta     ptr1+1
@@ -226,7 +359,7 @@ Z4:
        sta     tmp1
        ldy     #$00
 ccopy: lda     #$0F
-       sta     IndReg                  ; Access the system bank
+       sta     IndReg                  ; Access the system bank
 ccopy1:        lda     (ptr1),y
                sta     __VIDRAM_START__,y
                iny
@@ -238,7 +371,7 @@ ccopy2:     lda     __VIDRAM_START__,y
                iny
                bne     ccopy2
                inc     ptr1+1
-               inc     ptr2+1                  ; Bump high pointer bytes
+               inc     ptr2+1                  ; Bump high pointer bytes
                dec     tmp1
                bne     ccopy
 
@@ -257,7 +390,7 @@ ccopy2:     lda     __VIDRAM_START__,y
 ; CA (STATVID)   = 0
 ; CB (VICDOTSEL) = 0
 
-               ldy     #tpiCtrlReg
+               ldy     #TPI::CR
                lda     (tpi1),y
                sta     vidsave+0
                and     #%00001111
@@ -267,7 +400,7 @@ ccopy2:     lda     __VIDRAM_START__,y
 ; Set bit 14/15 of the VIC address range to the high bits of __VIDRAM_START__
 ; PC6/PC7 (VICBANKSEL 0/1) = 11
 
-               ldy     #tpiPortC
+               ldy     #TPI::PRC
                lda     (tpi2),y
                sta     vidsave+1
                and     #$3F
@@ -291,201 +424,161 @@ ccopy2: lda     __VIDRAM_START__,y
         lda     ExecReg
                sta     IndReg
 
-; Call module constructors
+; Activate chained interrupt handlers, then enable interrupts.
 
-               jsr     initlib
+        lda     #.lobyte(__INTERRUPTOR_COUNT__*2)
+        sta     irqcount
+       cli
 
-; Create the (empty) command line for the program
+; Call module constructors.
 
-               jsr     push0           ; argc
-               jsr     push0           ; argv
+        jsr    initlib
 
-; Execute the program code
+; Push arguments and call main()
 
-       jmp     Start
+               jsr     callmain
 
-; ------------------------------------------------------------------------
-; Additional data that we need for initialization and that's overwritten
-; later
-
-vectable:
-       jmp     $0000           ; CINT
-       jmp     $0000           ; IOINIT
-       jmp     $0000           ; RAMTAS
-       jmp     $0000           ; RESTOR
-       jmp     $0000           ; VECTOR
-       jmp     $0000           ; SETMSG
-       jmp     $0000           ; SECOND
-       jmp     $0000           ; TKSA
-       jmp     $0000           ; MEMTOP
-       jmp     $0000           ; MEMBOT
-       jmp     k_scnkey        ; SCNKEY
-       jmp     $0000           ; SETTMO
-       jmp     $0000           ; ACPTR
-       jmp     $0000           ; CIOUT
-       jmp     $0000           ; UNTLK
-       jmp     $0000           ; UNLSN
-       jmp     $0000           ; LISTEN
-       jmp     $0000           ; TALK
-       jmp     $0000           ; READST
-               jmp     k_setlfs        ; SETLFS
-               jmp     k_setnam        ; SETNAM
-       jmp     $0000           ; OPEN
-       jmp     $0000           ; CLOSE
-       jmp     $0000           ; CHKIN
-       jmp     $0000           ; CKOUT
-       jmp     $0000           ; CLRCH
-       jmp     $0000           ; BASIN
-       jmp     $0000           ; BSOUT
-       jmp     $0000           ; LOAD
-       jmp     $0000           ; SAVE
-       jmp     k_settim        ; SETTIM
-               jmp     k_rdtim         ; RDTIM
-       jmp     $0000           ; STOP
-       jmp     $0000           ; GETIN
-       jmp     $0000           ; CLALL
-       jmp     k_udtim         ; UDTIM
-       jmp     k_screen        ; SCREEN
-       jmp     k_plot          ; PLOT
-       jmp     k_iobase        ; IOBASE
-       sta     ExecReg
-       rts
-       .byte   $01             ; Filler
-               .word   nmi
-               .word   0               ; Reset - not used
-               .word   irq
-vectable_size  = * - vectable
+; Call module destructors. This is also the _exit entry and the default entry
+; point for the break vector.
 
-p3vectable:
-       .word   k_irq           ; IRQ user vector
-       .word   k_brk           ; BRK user vector
-       .word   k_nmi           ; NMI user vector
-p3vectable_size        = * - p3vectable
+_exit:  pha                    ; Save the return code on stack
+        jsr    donelib         ; Run module destructors
+       lda     #$00
+        sta     irqcount        ; Disable custom irq handlers
 
+; Address the system bank
 
-; ------------------------------------------------------------------------
-; This is the program code after setup. It starts at $400
+        lda     #$0F
+        sta     IndReg
 
-       .res    $400-*
+; Switch back the video to the system bank
 
-Start:
+       ldy     #TPI::CR
+       lda     vidsave+0
+       sta     (tpi1),y
 
-; Enable interrupts
+       ldy     #TPI::PRC
+       lda     vidsave+1
+       sta     (tpi2),y
 
-       cli
+        ldy    #VIC_VIDEO_ADR
+       lda     vidsave+2
+       sta     (vic),y
 
-; Call the user code
+; Copy stuff back from our zeropage to the systems
 
-               ldy     #4              ; Argument size
-               jsr     _main           ; call the users code
+.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
 
-; Call module destructors. This is also the _exit entry.
+; Place the program return code into ST
 
-_exit: jsr     donelib         ; Run module destructors
+       pla
+       ldy     #$9C            ; ST
+       sta     (sysp0),y
 
-; We need access to the system bank now
+; Setup the welcome code at the stack bottom in the system bank.
 
-       lda     #$0F
-       sta     IndReg
+        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
 
-; Switch back the video to the system bank
+; -------------------------------------------------------------------------
+; The IRQ handler goes into PAGE2. For performance reasons, and to allow
+; easier chaining, we do handle the IRQs in the execution bank (instead of
+; passing them to the system bank).
 
-       ldy     #tpiCtrlReg
-       lda     vidsave+0
-       sta     (tpi1),y
+; This is the mapping of the active irq register of the        6525 (tpi1):
+;
+; Bit   7       6       5       4       3       2       1       0
+;                               |       |       |       |       ^ 50 Hz
+;                               |       |       |       ^ SRQ IEEE 488
+;                               |       |       ^ cia
+;                               |       ^ IRQB ext. Port
+;                               ^ acia
+
+irq:    pha
+        txa
+        pha
+        tya
+        pha
+        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
 
-       ldy     #tpiPortC
-       lda     vidsave+1
-       sta     (tpi2),y
+; It's an IRQ
 
-        ldy    #VIC_VIDEO_ADR
-       lda     vidsave+2
-       sta     (vic),y
+        cld
 
-; Clear the start of the zero page, since it will be interpreted as a
-; (garbage) BASIC program otherwise. This is also the default entry for
-; the break vector.
+; Call chained IRQ handlers
 
-k_brk: sei
-       lda     #$00
-       ldx     #$3E
-Clear: sta     $02,x
-       dex
-       bne     Clear
-
-; Setup the welcome code at the stack bottom in the system bank. Use
-; the F4/F5 vector to access the system bank
-
-       ldy     #$00
-               sty     $F4
-       iny
-       sty     $F5
-       ldy     #reset_size-1
-@L1:   lda     reset,y
-       sta     ($F4),y
-       dey
-       bne     @L1
-       jmp     Back
+               ldy     irqcount
+        beq     irqskip
+               jsr     callirq_y               ; Call the functions
 
-; ------------------------------------------------------------------------
-; Code that is copied into the system bank at $100 when switching back
+; Done with chained IRQ handlers, check the TPI for IRQs and handle them
 
-reset: cli
-       jmp     $8000                   ; BASIC cold start
-reset_size = * - reset
+irqskip:lda    #$0F
+       sta     IndReg
+       ldy     #TPI::AIR
+       lda     (tpi1),y                ; Interrupt Register 6525
+       beq     noirq
 
-; ------------------------------------------------------------------------
-; Code for a few simpler kernal calls goes here
-
-k_iobase:
-       ldx     cia2
-       ldy     cia2+1
-       rts
-
-k_screen:
-               ldx     #40             ; Columns
-       ldy     #25             ; Lines
-       rts
-
-k_setlfs:
-        sta     LogicalAdr
-        stx     FirstAdr
-        sty     SecondAdr
-        rts
+; 50/60Hz interrupt
 
-k_setnam:
-        sta     FileNameLen
-        lda     $00,x
-        sta     FileNameAdrLo
-        lda     $01,x
-        sta     FileNameAdrHi
-        lda     $02,x
-        sta     FileNameAdrSeg
-        rts
+       cmp     #%00000001              ; ticker irq?
+       bne     irqend
+               jsr     scnkey                  ; Poll the keyboard
+        jsr    UDTIM                   ; Bump the time
 
-k_rdtim:
-       sei
-       lda     time+0
-       ldx     time+1
-       ldy     time+2
-       cli
-       rts
-
-k_settim:
-       sei
-       sta     time+0
-       stx     time+1
-       sty     time+2
-       cli
-       rts
+; Done
 
-; -------------------------------------------------------------------------
-; Data area - switch back to relocatable mode
+irqend:        ldy     #TPI::AIR
+               sta     (tpi1),y                ; Clear interrupt
+
+noirq: pla
+        sta     IndReg
+        pla
+        tay
+        pla
+        tax
+        pla
+nmi:   rti
 
-       .reloc
+dobrk:  jmp    (BRKVec)
+
+; -------------------------------------------------------------------------
+; Data area
 
 .data
-spsave:        .res    1
 vidsave:.res   3
 
+.bss
+irqcount:       .byte   0
+